mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-04 02:10:04 +01:00
Compare commits
96 Commits
issue/3296
...
feature/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c4b30eb44 | ||
|
|
16937cf2af | ||
|
|
032e3d5dee | ||
|
|
54801f09f1 | ||
|
|
29587e48e7 | ||
|
|
c2fe908e18 | ||
|
|
d55fc53884 | ||
|
|
cf0a0d7ca9 | ||
|
|
139815ceb3 | ||
|
|
9311ac2579 | ||
|
|
27ba536872 | ||
|
|
18efa0559c | ||
|
|
b27e1081ae | ||
|
|
b3e7c9d227 | ||
|
|
39869bcaae | ||
|
|
fb17678b01 | ||
|
|
315824f4ef | ||
|
|
36907ad6f2 | ||
|
|
8bacded9c4 | ||
|
|
5a3ccb3b60 | ||
|
|
00529713fd | ||
|
|
e0868b099a | ||
|
|
49cc504d94 | ||
|
|
18c6d6b0f3 | ||
|
|
4d1f92199c | ||
|
|
dca532cf4b | ||
|
|
b5991642f8 | ||
|
|
84b39a9edc | ||
|
|
67d96b0a13 | ||
|
|
c5d4f992c1 | ||
|
|
11b406feee | ||
|
|
182e521730 | ||
|
|
256af8f6e0 | ||
|
|
87c65f9eec | ||
|
|
971c7e9fba | ||
|
|
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 |
1
.github/actions/spell-check/excludes.txt
vendored
1
.github/actions/spell-check/excludes.txt
vendored
@@ -101,6 +101,7 @@
|
||||
^doc/devdocs/akaLinks\.md$
|
||||
^NOTICE\.md$
|
||||
^src/common/CalculatorEngineCommon/exprtk\.hpp$
|
||||
^src/common/UnitTests-CommonUtils/
|
||||
^src/common/ManagedCommon/ColorFormatHelper\.cs$
|
||||
^src/common/notifications/BackgroundActivatorDLL/cpp\.hint$
|
||||
^src/common/sysinternals/Eula/
|
||||
|
||||
108
.github/actions/spell-check/expect.txt
vendored
108
.github/actions/spell-check/expect.txt
vendored
@@ -11,6 +11,7 @@ ACCESSDENIED
|
||||
ACCESSTOKEN
|
||||
acfs
|
||||
ACIE
|
||||
ACR
|
||||
AClient
|
||||
AColumn
|
||||
acrt
|
||||
@@ -44,6 +45,7 @@ ALLCHILDREN
|
||||
ALLINPUT
|
||||
Allman
|
||||
Allmodule
|
||||
ALLNOISE
|
||||
ALLOWUNDO
|
||||
ALLVIEW
|
||||
ALPHATYPE
|
||||
@@ -57,7 +59,6 @@ AOC
|
||||
aocfnapldcnfbofgmbbllojgocaelgdd
|
||||
AOklab
|
||||
aot
|
||||
APARTMENTTHREADED
|
||||
APeriod
|
||||
apicontract
|
||||
apidl
|
||||
@@ -95,6 +96,7 @@ asf
|
||||
Ashcraft
|
||||
AShortcut
|
||||
ASingle
|
||||
ASUS
|
||||
ASSOCCHANGED
|
||||
ASSOCF
|
||||
ASSOCSTR
|
||||
@@ -104,6 +106,7 @@ atl
|
||||
ATRIOX
|
||||
aumid
|
||||
authenticode
|
||||
AUO
|
||||
AUTOBUDDY
|
||||
AUTOCHECKBOX
|
||||
AUTOHIDE
|
||||
@@ -121,6 +124,10 @@ azureaiinference
|
||||
azureinference
|
||||
azureopenai
|
||||
backticks
|
||||
Backlight
|
||||
Badflags
|
||||
Badmode
|
||||
Badparam
|
||||
bbwe
|
||||
BCIE
|
||||
bck
|
||||
@@ -129,6 +136,7 @@ bezelled
|
||||
bhid
|
||||
BIF
|
||||
bigbar
|
||||
BIGGERSIZEOK
|
||||
bigobj
|
||||
binlog
|
||||
binres
|
||||
@@ -193,6 +201,7 @@ Carlseibert
|
||||
CAtl
|
||||
caub
|
||||
CBN
|
||||
Cds
|
||||
cch
|
||||
CCHDEVICENAME
|
||||
CCHFORMNAME
|
||||
@@ -212,6 +221,7 @@ checkmarks
|
||||
CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
CHOOSEFONT
|
||||
Chunghwa
|
||||
CIBUILD
|
||||
cidl
|
||||
CIELCh
|
||||
@@ -226,7 +236,7 @@ claude
|
||||
CLEARTYPE
|
||||
clickable
|
||||
clickonce
|
||||
CLIENTEDGE
|
||||
clientedge
|
||||
clientid
|
||||
clientside
|
||||
CLIPBOARDUPDATE
|
||||
@@ -238,6 +248,7 @@ CLSCTX
|
||||
clsids
|
||||
Clusion
|
||||
cmder
|
||||
CMN
|
||||
CMDNOTFOUNDMODULEINTERFACE
|
||||
cmdpal
|
||||
CMIC
|
||||
@@ -292,6 +303,7 @@ Corpor
|
||||
cotaskmem
|
||||
COULDNOT
|
||||
countof
|
||||
Cowait
|
||||
covrun
|
||||
cpcontrols
|
||||
cph
|
||||
@@ -310,11 +322,14 @@ CRECT
|
||||
CRH
|
||||
critsec
|
||||
cropandlock
|
||||
crt
|
||||
CROPTOSQUARE
|
||||
Crossdevice
|
||||
csdevkit
|
||||
CSearch
|
||||
CSettings
|
||||
cso
|
||||
CSOT
|
||||
CSRW
|
||||
CStyle
|
||||
cswin
|
||||
@@ -357,11 +372,14 @@ DBPROPIDSET
|
||||
DBPROPSET
|
||||
DBT
|
||||
DCBA
|
||||
DCapabilities
|
||||
DCOM
|
||||
DComposition
|
||||
DCR
|
||||
ddc
|
||||
DDEIf
|
||||
Deact
|
||||
debouncer
|
||||
debugbreak
|
||||
decryptor
|
||||
Dedup
|
||||
@@ -379,6 +397,7 @@ DEFAULTTOPRIMARY
|
||||
DEFERERASE
|
||||
DEFPUSHBUTTON
|
||||
deinitialization
|
||||
DELA
|
||||
DELETEDKEYIMAGE
|
||||
DELETESCANS
|
||||
DEMOTYPE
|
||||
@@ -413,18 +432,20 @@ DISABLEASACTIONKEY
|
||||
DISABLENOSCROLL
|
||||
diskmgmt
|
||||
DISPLAYCHANGE
|
||||
DISPLAYCONFIG
|
||||
displayconfig
|
||||
DISPLAYFLAGS
|
||||
DISPLAYFREQUENCY
|
||||
displayname
|
||||
DISPLAYORIENTATION
|
||||
diu
|
||||
divyan
|
||||
Dlg
|
||||
DLGFRAME
|
||||
DLGMODALFRAME
|
||||
dlgmodalframe
|
||||
dlib
|
||||
dllhost
|
||||
dllmain
|
||||
Dmdo
|
||||
DNLEN
|
||||
DONOTROUND
|
||||
DONTVALIDATEPATH
|
||||
@@ -434,6 +455,7 @@ downsampling
|
||||
downscale
|
||||
DPICHANGED
|
||||
DPIs
|
||||
DPMS
|
||||
DPSAPI
|
||||
DQTAT
|
||||
DQTYPE
|
||||
@@ -471,15 +493,19 @@ DWMWINDOWMAXIMIZEDCHANGE
|
||||
DWORDLONG
|
||||
dworigin
|
||||
dwrite
|
||||
Dxva
|
||||
dxgi
|
||||
eab
|
||||
EAccess
|
||||
easeofaccess
|
||||
ecount
|
||||
Edid
|
||||
edid
|
||||
EDITKEYBOARD
|
||||
EDITSHORTCUTS
|
||||
EDITTEXT
|
||||
EFile
|
||||
EInvalid
|
||||
eep
|
||||
eku
|
||||
emojis
|
||||
ENABLEDELAYEDEXPANSION
|
||||
@@ -489,14 +515,15 @@ ENABLETEMPLATE
|
||||
encodedlaunch
|
||||
encryptor
|
||||
ENDSESSION
|
||||
ENot
|
||||
ENSUREVISIBLE
|
||||
ENTERSIZEMOVE
|
||||
ENTRYW
|
||||
ENU
|
||||
environmentvariables
|
||||
EOAC
|
||||
EPO
|
||||
epu
|
||||
EProvider
|
||||
ERASEBKGND
|
||||
EREOF
|
||||
EResize
|
||||
@@ -550,6 +577,7 @@ fdx
|
||||
FErase
|
||||
fesf
|
||||
FFFF
|
||||
FFh
|
||||
Figma
|
||||
FILEEXPLORER
|
||||
fileexploreraddons
|
||||
@@ -592,6 +620,7 @@ formatetc
|
||||
FORPARSING
|
||||
foundrylocal
|
||||
FRAMECHANGED
|
||||
Framechanged
|
||||
FRestore
|
||||
frm
|
||||
FROMTOUCH
|
||||
@@ -635,6 +664,7 @@ GMEM
|
||||
GNumber
|
||||
googleai
|
||||
googlegemini
|
||||
Gotchas
|
||||
gpedit
|
||||
gpo
|
||||
GPOCA
|
||||
@@ -647,13 +677,13 @@ GSM
|
||||
gtm
|
||||
guiddata
|
||||
GUITHREADINFO
|
||||
Gotcha
|
||||
Gotchas
|
||||
GValue
|
||||
gwl
|
||||
GWLP
|
||||
GWLSTYLE
|
||||
hangeul
|
||||
Hann
|
||||
Hantai
|
||||
Hanzi
|
||||
Hardlines
|
||||
hardlinks
|
||||
@@ -712,6 +742,7 @@ HKPD
|
||||
HKU
|
||||
HMD
|
||||
hmenu
|
||||
HMON
|
||||
hmodule
|
||||
hmonitor
|
||||
homies
|
||||
@@ -729,6 +760,7 @@ hotkeys
|
||||
hotlight
|
||||
hotspot
|
||||
HPAINTBUFFER
|
||||
HPhysical
|
||||
HRAWINPUT
|
||||
hredraw
|
||||
hres
|
||||
@@ -739,6 +771,7 @@ hsb
|
||||
HSCROLL
|
||||
hsi
|
||||
HSpeed
|
||||
HSync
|
||||
HTCLIENT
|
||||
hthumbnail
|
||||
HTOUCHINPUT
|
||||
@@ -748,6 +781,7 @@ HVal
|
||||
HValue
|
||||
Hvci
|
||||
hwb
|
||||
HWP
|
||||
HWHEEL
|
||||
HWINEVENTHOOK
|
||||
hwnd
|
||||
@@ -761,6 +795,7 @@ IAI
|
||||
icf
|
||||
ICONERROR
|
||||
ICONLOCATION
|
||||
ICONONLY
|
||||
IDCANCEL
|
||||
IDD
|
||||
idk
|
||||
@@ -804,6 +839,7 @@ INITTOLOGFONTSTRUCT
|
||||
INLINEPREFIX
|
||||
inlines
|
||||
Inno
|
||||
Innolux
|
||||
INPC
|
||||
inproc
|
||||
INPUTHARDWARE
|
||||
@@ -845,6 +881,7 @@ istep
|
||||
ith
|
||||
ITHUMBNAIL
|
||||
IUI
|
||||
IVO
|
||||
IUWP
|
||||
IWIC
|
||||
jeli
|
||||
@@ -858,6 +895,7 @@ jpnime
|
||||
Jsons
|
||||
jsonval
|
||||
jxr
|
||||
Kantai
|
||||
keybd
|
||||
KEYBDDATA
|
||||
KEYBDINPUT
|
||||
@@ -879,6 +917,7 @@ KILLFOCUS
|
||||
killrunner
|
||||
kmph
|
||||
kvp
|
||||
KVM
|
||||
Kybd
|
||||
LARGEICON
|
||||
lastcodeanalysissucceeded
|
||||
@@ -894,12 +933,15 @@ Lclean
|
||||
Ldone
|
||||
Ldr
|
||||
LEFTALIGN
|
||||
leftclick
|
||||
LEFTSCROLLBAR
|
||||
LEFTTEXT
|
||||
leftclick
|
||||
LError
|
||||
LEVELID
|
||||
LExit
|
||||
Lenovo
|
||||
LGD
|
||||
LFU
|
||||
lhwnd
|
||||
LIBFUZZER
|
||||
LIBID
|
||||
@@ -1004,6 +1046,7 @@ MAPTOSAMESHORTCUT
|
||||
MAPVK
|
||||
MARKDOWNPREVIEWHANDLERCPP
|
||||
MAXIMIZEBOX
|
||||
Maximizebox
|
||||
MAXSHORTCUTSIZE
|
||||
maxversiontested
|
||||
mber
|
||||
@@ -1016,12 +1059,14 @@ MDL
|
||||
mdtext
|
||||
mdtxt
|
||||
mdwn
|
||||
mccs
|
||||
meme
|
||||
memicmp
|
||||
MENUITEMINFO
|
||||
MENUITEMINFOW
|
||||
MERGECOPY
|
||||
MERGEPAINT
|
||||
Metacharacter
|
||||
metadatamatters
|
||||
Metadatas
|
||||
metafile
|
||||
@@ -1036,6 +1081,7 @@ mikeclayton
|
||||
mindaro
|
||||
Minimizable
|
||||
MINIMIZEBOX
|
||||
Minimizebox
|
||||
MINIMIZEEND
|
||||
MINIMIZESTART
|
||||
MINMAXINFO
|
||||
@@ -1071,7 +1117,8 @@ mouseutils
|
||||
MOVESIZEEND
|
||||
MOVESIZESTART
|
||||
MRM
|
||||
MRT
|
||||
Mrt
|
||||
mrt
|
||||
mru
|
||||
MSAL
|
||||
msc
|
||||
@@ -1097,6 +1144,7 @@ Mso
|
||||
msrc
|
||||
msstore
|
||||
mstsc
|
||||
mswhql
|
||||
msvcp
|
||||
MT
|
||||
MTND
|
||||
@@ -1114,6 +1162,7 @@ MYICON
|
||||
myorg
|
||||
myrepo
|
||||
NAMECHANGE
|
||||
Nanjing
|
||||
namespaceanddescendants
|
||||
nao
|
||||
NCACTIVATE
|
||||
@@ -1182,6 +1231,7 @@ NOMCX
|
||||
NOMINMAX
|
||||
NOMIRRORBITMAP
|
||||
NOMOVE
|
||||
Nomove
|
||||
NONANTIALIASED
|
||||
nonclient
|
||||
NONCLIENTMETRICSW
|
||||
@@ -1203,6 +1253,7 @@ NORMALUSER
|
||||
NOSEARCH
|
||||
NOSENDCHANGING
|
||||
NOSIZE
|
||||
Nosize
|
||||
NOTHOUSANDS
|
||||
NOTICKS
|
||||
NOTIFICATIONSDLL
|
||||
@@ -1210,9 +1261,11 @@ NOTIFYICONDATA
|
||||
NOTIFYICONDATAW
|
||||
NOTIMPL
|
||||
NOTOPMOST
|
||||
Notopmost
|
||||
NOTRACK
|
||||
NOTSRCCOPY
|
||||
NOTSRCERASE
|
||||
Notupdated
|
||||
notwindows
|
||||
NOTXORPEN
|
||||
nowarn
|
||||
@@ -1256,6 +1309,7 @@ opensource
|
||||
openurl
|
||||
openxmlformats
|
||||
OPTIMIZEFORINVOKE
|
||||
Optronics
|
||||
ORPHANEDDIALOGTITLE
|
||||
ORSCANS
|
||||
oss
|
||||
@@ -1291,6 +1345,7 @@ PATINVERT
|
||||
PATPAINT
|
||||
pbc
|
||||
pbi
|
||||
PBP
|
||||
PBlob
|
||||
pbrush
|
||||
pcb
|
||||
@@ -1305,6 +1360,7 @@ PDBs
|
||||
PDEVMODE
|
||||
pdisp
|
||||
PDLL
|
||||
pdmodels
|
||||
pdo
|
||||
pdto
|
||||
pdtobj
|
||||
@@ -1327,6 +1383,7 @@ pguid
|
||||
phbm
|
||||
phbmp
|
||||
phicon
|
||||
PHL
|
||||
Photoshop
|
||||
phwnd
|
||||
pici
|
||||
@@ -1359,6 +1416,8 @@ Popups
|
||||
POPUPWINDOW
|
||||
POSITIONITEM
|
||||
POWERBROADCAST
|
||||
powerdisplay
|
||||
POWERDISPLAYMODULEINTERFACE
|
||||
POWERRENAMECONTEXTMENU
|
||||
powerrenameinput
|
||||
POWERRENAMETEST
|
||||
@@ -1413,6 +1472,7 @@ projectname
|
||||
PROPERTYKEY
|
||||
Propset
|
||||
PROPVARIANT
|
||||
prot
|
||||
PRTL
|
||||
prvpane
|
||||
psapi
|
||||
@@ -1440,12 +1500,16 @@ PTOKEN
|
||||
PToy
|
||||
ptstr
|
||||
pui
|
||||
pvct
|
||||
PWAs
|
||||
pwcs
|
||||
PWSTR
|
||||
pwsz
|
||||
pwtd
|
||||
Qdc
|
||||
QDC
|
||||
qdc
|
||||
QDS
|
||||
qit
|
||||
QITAB
|
||||
QITABENT
|
||||
@@ -1489,7 +1553,9 @@ regfile
|
||||
REGISTERCLASSFAILED
|
||||
REGISTRYHEADER
|
||||
REGISTRYPREVIEWEXT
|
||||
registryroot
|
||||
regkey
|
||||
regroot
|
||||
regsvr
|
||||
REINSTALLMODE
|
||||
releaseblog
|
||||
@@ -1534,7 +1600,6 @@ riid
|
||||
RKey
|
||||
RNumber
|
||||
rollups
|
||||
ROOTOWNER
|
||||
rop
|
||||
ROUNDSMALL
|
||||
ROWSETEXT
|
||||
@@ -1667,6 +1732,7 @@ sigdn
|
||||
Signedness
|
||||
SIGNINGSCENARIO
|
||||
signtool
|
||||
SIIGBF
|
||||
SINGLEKEY
|
||||
sipolicy
|
||||
SIZEBOX
|
||||
@@ -1731,6 +1797,7 @@ STARTUPINFOW
|
||||
startupscreen
|
||||
STATFLAG
|
||||
STATICEDGE
|
||||
Staticedge
|
||||
staticmethod
|
||||
STATSTG
|
||||
stdafx
|
||||
@@ -1767,6 +1834,7 @@ subkeys
|
||||
sublang
|
||||
SUBMODULEUPDATE
|
||||
subresource
|
||||
swp
|
||||
Superbar
|
||||
sut
|
||||
svchost
|
||||
@@ -1775,7 +1843,8 @@ SVGIO
|
||||
svgz
|
||||
SVSI
|
||||
SWFO
|
||||
swp
|
||||
SWP
|
||||
Swp
|
||||
SWPNOSIZE
|
||||
SWPNOZORDER
|
||||
SWRESTORE
|
||||
@@ -1835,7 +1904,9 @@ THEMECHANGED
|
||||
themeresources
|
||||
THH
|
||||
THICKFRAME
|
||||
Thickframe
|
||||
THISCOMPONENT
|
||||
Tianma
|
||||
throughs
|
||||
TILEDWINDOW
|
||||
TILLSON
|
||||
@@ -1916,13 +1987,13 @@ UNLEN
|
||||
UNORM
|
||||
unremapped
|
||||
Unsubscribes
|
||||
unsubscribes
|
||||
unvirtualized
|
||||
unwide
|
||||
unzoom
|
||||
UOffset
|
||||
UOI
|
||||
UPDATENOW
|
||||
UPDATEREGISTRY
|
||||
updown
|
||||
UPGRADINGPRODUCTCODE
|
||||
upscaling
|
||||
@@ -1949,6 +2020,8 @@ vcamp
|
||||
vcenter
|
||||
vcgtq
|
||||
VCINSTALLDIR
|
||||
vcp
|
||||
vcpname
|
||||
Vcpkg
|
||||
VCRT
|
||||
vcruntime
|
||||
@@ -1961,6 +2034,8 @@ VERIFYCONTEXT
|
||||
VERSIONINFO
|
||||
VERTRES
|
||||
VERTSIZE
|
||||
VESA
|
||||
vesa
|
||||
VFT
|
||||
vget
|
||||
vgetq
|
||||
@@ -1992,6 +2067,7 @@ VSM
|
||||
vso
|
||||
vsonline
|
||||
VSpeed
|
||||
VSync
|
||||
vstemplate
|
||||
vstest
|
||||
VSTHRD
|
||||
@@ -2033,7 +2109,7 @@ winapi
|
||||
winappsdk
|
||||
windir
|
||||
WINDOWCREATED
|
||||
WINDOWEDGE
|
||||
windowedge
|
||||
WINDOWINFO
|
||||
WINDOWNAME
|
||||
WINDOWPLACEMENT
|
||||
@@ -2057,12 +2133,12 @@ WINL
|
||||
winlogon
|
||||
winmd
|
||||
winml
|
||||
WINNT
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
winsta
|
||||
WINTHRESHOLD
|
||||
WINNT
|
||||
WINVER
|
||||
winxamlmanager
|
||||
withinrafael
|
||||
@@ -2074,6 +2150,7 @@ WKSG
|
||||
Wlkr
|
||||
wmain
|
||||
Wman
|
||||
wmi
|
||||
WMI
|
||||
WMICIM
|
||||
wmimgmt
|
||||
@@ -2086,6 +2163,7 @@ WNDCLASSEX
|
||||
WNDCLASSEXW
|
||||
WNDCLASSW
|
||||
WNDPROC
|
||||
Wndproc
|
||||
wnode
|
||||
wom
|
||||
WORKSPACESEDITOR
|
||||
|
||||
13
.github/actions/spell-check/patterns.txt
vendored
13
.github/actions/spell-check/patterns.txt
vendored
@@ -274,5 +274,18 @@ St&yle
|
||||
# 0x6f677548 is user name but user folder causes a flag
|
||||
\bx6f677548\b
|
||||
|
||||
# Windows API constants and hardware interface terms
|
||||
\bCOINIT[_A-Z]*\b
|
||||
\bEOAC[_A-Z]*\b
|
||||
\b(?:RPC_C_AUTHN_)?WINNT\b
|
||||
\bUPDATEREGISTRY\b
|
||||
\b(?:CDS_)?UPDATEREGISTRY\b
|
||||
|
||||
# Display interface terms (HDMI, DVI, DisplayPort)
|
||||
\b(?:HDMI|DVI|DisplayPort)(?:-\d+)?\b
|
||||
|
||||
# 2D Region struct names
|
||||
\bDisplayConfig2?D?Region\b
|
||||
|
||||
# Microsoft Store URLs and product IDs
|
||||
ms-windows-store://\S+
|
||||
|
||||
@@ -31,82 +31,59 @@
|
||||
"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",
|
||||
|
||||
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.exe",
|
||||
@@ -129,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",
|
||||
@@ -142,7 +118,6 @@
|
||||
"PowerToys.ImageResizerContextMenu.dll",
|
||||
"ImageResizerContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.LightSwitchModuleInterface.dll",
|
||||
"LightSwitchService\\PowerToys.LightSwitchService.exe",
|
||||
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
@@ -178,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",
|
||||
@@ -194,7 +168,6 @@
|
||||
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
"PowerToys.MouseWithoutBordersService.dll",
|
||||
"PowerToys.MouseWithoutBordersService.exe",
|
||||
"PowerToys.MouseWithoutBordersHelper.dll",
|
||||
@@ -207,9 +180,13 @@
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
|
||||
"PowerToys.PowerDisplayModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerDisplay.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerDisplay.exe",
|
||||
"PowerDisplay.Lib.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.PowerRenameExt.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerRename.exe",
|
||||
"WinUI3Apps\\PowerToys.PowerRenameContextMenu.dll",
|
||||
@@ -222,7 +199,6 @@
|
||||
"PowerToys.WorkspacesEditor.dll",
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
@@ -231,16 +207,13 @@
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"PowerToys.ModuleContracts.dll",
|
||||
"Awake.ModuleServices.dll",
|
||||
@@ -378,6 +351,8 @@
|
||||
"UnitsNet.dll",
|
||||
"UtfUnknown.dll",
|
||||
"Wpf.Ui.dll",
|
||||
"WmiLight.dll",
|
||||
"WmiLight.Native.dll",
|
||||
"Shmuelie.WinRTServer.dll",
|
||||
"ToolGood.Words.Pinyin.dll"
|
||||
],
|
||||
|
||||
@@ -91,6 +91,7 @@ extends:
|
||||
official: true
|
||||
codeSign: true
|
||||
runTests: false
|
||||
buildTests: false
|
||||
signingIdentity:
|
||||
serviceName: $(SigningServiceName)
|
||||
appId: $(SigningAppId)
|
||||
|
||||
@@ -258,6 +258,7 @@ jobs:
|
||||
-restore -graph
|
||||
/p:RestorePackagesConfig=true
|
||||
/p:CIBuild=true
|
||||
/p:BuildTests=${{ parameters.buildTests }}
|
||||
/bl:$(LogOutputDirectory)\build-0-main.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
$(MSBuildCacheParameters)
|
||||
|
||||
@@ -59,6 +59,7 @@ stages:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
msBuildCacheIsReadOnly: ${{ parameters.msBuildCacheIsReadOnly }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
buildTests: true
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
|
||||
${{ if eq(parameters.useLatestWinAppSDK, true) }}:
|
||||
@@ -78,7 +79,9 @@ stages:
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
demands: ImageOverride -equals SHINE-VS18-Preview
|
||||
${{ else }}:
|
||||
demands: ImageOverride -equals SHINE-VS18-Latest
|
||||
buildConfigurations: [Release]
|
||||
official: false
|
||||
codeSign: false
|
||||
|
||||
@@ -90,9 +90,15 @@ if ($noticeMatch.Success) {
|
||||
$currentNoticePackageList = ""
|
||||
}
|
||||
|
||||
# Test-only packages that are allowed to be in NOTICE.md but not in the build
|
||||
# (e.g., when BuildTests=false, these packages won't appear in the NuGet list)
|
||||
$allowedExtraPackages = @(
|
||||
"- Moq"
|
||||
)
|
||||
|
||||
if (!$noticeFile.Trim().EndsWith($returnList.Trim()))
|
||||
{
|
||||
Write-Host -ForegroundColor Red "Notice.md does not match NuGet list."
|
||||
Write-Host -ForegroundColor Yellow "Notice.md does not exactly match NuGet list. Analyzing differences..."
|
||||
|
||||
# Show detailed differences
|
||||
$generatedPackages = $returnList -split "`r`n|`n" | Where-Object { $_.Trim() -ne "" } | Sort-Object
|
||||
@@ -105,7 +111,7 @@ if (!$noticeFile.Trim().EndsWith($returnList.Trim()))
|
||||
# Find packages in proj file list but not in NOTICE.md
|
||||
$missingFromNotice = $generatedPackages | Where-Object { $noticePackages -notcontains $_ }
|
||||
if ($missingFromNotice.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Red "MissingFromNotice:"
|
||||
Write-Host -ForegroundColor Red "MissingFromNotice (ERROR - these must be added to NOTICE.md):"
|
||||
foreach ($pkg in $missingFromNotice) {
|
||||
Write-Host -ForegroundColor Red " $pkg"
|
||||
}
|
||||
@@ -114,10 +120,23 @@ if (!$noticeFile.Trim().EndsWith($returnList.Trim()))
|
||||
|
||||
# Find packages in NOTICE.md but not in proj file list
|
||||
$extraInNotice = $noticePackages | Where-Object { $generatedPackages -notcontains $_ }
|
||||
if ($extraInNotice.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Yellow "ExtraInNotice:"
|
||||
foreach ($pkg in $extraInNotice) {
|
||||
Write-Host -ForegroundColor Yellow " $pkg"
|
||||
|
||||
# Filter out allowed extra packages (test-only dependencies)
|
||||
$unexpectedExtra = $extraInNotice | Where-Object { $allowedExtraPackages -notcontains $_ }
|
||||
$allowedExtra = $extraInNotice | Where-Object { $allowedExtraPackages -contains $_ }
|
||||
|
||||
if ($allowedExtra.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Green "ExtraInNotice (OK - allowed test-only packages):"
|
||||
foreach ($pkg in $allowedExtra) {
|
||||
Write-Host -ForegroundColor Green " $pkg"
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
if ($unexpectedExtra.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Red "ExtraInNotice (ERROR - unexpected packages in NOTICE.md):"
|
||||
foreach ($pkg in $unexpectedExtra) {
|
||||
Write-Host -ForegroundColor Red " $pkg"
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
@@ -127,10 +146,17 @@ if (!$noticeFile.Trim().EndsWith($returnList.Trim()))
|
||||
Write-Host " Proj file list has $($generatedPackages.Count) packages"
|
||||
Write-Host " NOTICE.md has $($noticePackages.Count) packages"
|
||||
Write-Host " MissingFromNotice: $($missingFromNotice.Count) packages"
|
||||
Write-Host " ExtraInNotice: $($extraInNotice.Count) packages"
|
||||
Write-Host " ExtraInNotice (allowed): $($allowedExtra.Count) packages"
|
||||
Write-Host " ExtraInNotice (unexpected): $($unexpectedExtra.Count) packages"
|
||||
Write-Host ""
|
||||
|
||||
exit 1
|
||||
# Fail if there are missing packages OR unexpected extra packages
|
||||
if ($missingFromNotice.Count -gt 0 -or $unexpectedExtra.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Red "FAILED: NOTICE.md mismatch detected."
|
||||
exit 1
|
||||
} else {
|
||||
Write-Host -ForegroundColor Green "PASSED: NOTICE.md matches (with allowed test-only packages)."
|
||||
}
|
||||
}
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -2,6 +2,23 @@
|
||||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- Skip building C++ test projects when BuildTests=false -->
|
||||
<PropertyGroup Condition="'$(_IsSkippedTestProject)' == 'true'">
|
||||
<UsePrecompiledHeaders>false</UsePrecompiledHeaders>
|
||||
<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">
|
||||
|
||||
@@ -19,6 +19,39 @@
|
||||
<PlatformTarget>$(Platform)</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Completely skip building test projects when BuildTests=false (e.g., Release pipeline).
|
||||
This avoids InternalsVisibleTo/signing issues by not compiling test code at all.
|
||||
Match: projects ending in Test, Tests, UnitTests, UITests, FuzzTests, or in a folder named Tests.
|
||||
Also matches projects starting with UnitTests- (e.g., UnitTests-CommonLib).
|
||||
Also removes all PackageReference/ProjectReference to prevent NuGet restore and dependency builds.
|
||||
Note: Checking both 'false' and 'False' to handle YAML boolean serialization.
|
||||
-->
|
||||
<PropertyGroup Condition="'$(BuildTests)' == 'false' or '$(BuildTests)' == 'False'">
|
||||
<_ProjectName>$(MSBuildProjectName)</_ProjectName>
|
||||
<!-- Match any project ending with "Test" or "Tests" (covers UnitTests, UITests, FuzzTests, etc.) -->
|
||||
<_IsSkippedTestProject Condition="$(_ProjectName.EndsWith('Test'))">true</_IsSkippedTestProject>
|
||||
<_IsSkippedTestProject Condition="$(_ProjectName.EndsWith('Tests'))">true</_IsSkippedTestProject>
|
||||
<!-- Match projects starting with UnitTests- or UITest- prefix -->
|
||||
<_IsSkippedTestProject Condition="$(_ProjectName.StartsWith('UnitTests-'))">true</_IsSkippedTestProject>
|
||||
<_IsSkippedTestProject Condition="$(_ProjectName.StartsWith('UITest-'))">true</_IsSkippedTestProject>
|
||||
<!-- Match projects in a Tests folder -->
|
||||
<_IsSkippedTestProject Condition="$(MSBuildProjectDirectory.Contains('\Tests\'))">true</_IsSkippedTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(_IsSkippedTestProject)' == 'true'">
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateGlobalUsings>false</GenerateGlobalUsings>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<!-- Disable all code analysis for skipped test projects -->
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<RunAnalyzers>false</RunAnalyzers>
|
||||
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.csproj'">
|
||||
<Version>$(Version).0</Version>
|
||||
<RepositoryUrl>https://github.com/microsoft/PowerToys</RepositoryUrl>
|
||||
@@ -30,7 +63,9 @@
|
||||
<_PropertySheetDisplayName>PowerToys.Root.Props</_PropertySheetDisplayName>
|
||||
<ForceImportBeforeCppProps>$(MsbuildThisFileDirectory)\Cpp.Build.props</ForceImportBeforeCppProps>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(MSBuildProjectExtension)' == '.csproj'">
|
||||
|
||||
|
||||
<ItemGroup Condition="'$(MSBuildProjectExtension)' == '.csproj' and '$(_IsSkippedTestProject)' != 'true'">
|
||||
<PackageReference Include="StyleCop.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -28,4 +28,41 @@
|
||||
<PropertyGroup Condition="'$(IgnoreExperimentalWarnings)' == 'true'">
|
||||
<NoWarn>$(NoWarn);CS8305;SA1500;CA1852</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
<!-- Skipped test projects when BuildTests=false: no-op build and remove references.
|
||||
This must be in targets (not props) so it runs AFTER the project file adds its items. -->
|
||||
<PropertyGroup Condition="'$(_IsSkippedTestProject)' == 'true'">
|
||||
<BuildDependsOn />
|
||||
<CoreBuildDependsOn />
|
||||
<RebuildDependsOn />
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- For C# projects: remove all items -->
|
||||
<ItemGroup Condition="'$(_IsSkippedTestProject)' == 'true' and '$(MSBuildProjectExtension)' == '.csproj'">
|
||||
<PackageReference Remove="@(PackageReference)" />
|
||||
<ProjectReference Remove="@(ProjectReference)" />
|
||||
<Reference Remove="@(Reference)" />
|
||||
<Compile Remove="@(Compile)" />
|
||||
<Content Remove="@(Content)" />
|
||||
<EmbeddedResource Remove="@(EmbeddedResource)" />
|
||||
<None Remove="@(None)" />
|
||||
<Using Remove="@(Using)" />
|
||||
<GlobalUsing Remove="@(GlobalUsing)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- For C++ projects (vcxproj): remove all compile/link items to prevent build -->
|
||||
<ItemGroup Condition="'$(_IsSkippedTestProject)' == 'true' and '$(MSBuildProjectExtension)' == '.vcxproj'">
|
||||
<ClCompile Remove="@(ClCompile)" />
|
||||
<ClInclude Remove="@(ClInclude)" />
|
||||
<Link Remove="@(Link)" />
|
||||
<Lib Remove="@(Lib)" />
|
||||
<ProjectReference Remove="@(ProjectReference)" />
|
||||
<None Remove="@(None)" />
|
||||
<ResourceCompile Remove="@(ResourceCompile)" />
|
||||
<Midl Remove="@(Midl)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Note: For C++ skipped test projects, build is effectively skipped by removing all compile items above.
|
||||
We don't define empty Build/Rebuild/Clean targets here because MSBuild Target definitions with Condition
|
||||
on the Target element still override the default targets even when condition is false. -->
|
||||
</Project>
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
<PackageVersion Include="OpenAI" Version="2.5.0" />
|
||||
<PackageVersion Include="Polly.Core" Version="8.6.5" />
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
@@ -104,6 +105,7 @@
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Collections.Immutable" Version="9.0.0" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.10" />
|
||||
@@ -133,6 +135,7 @@
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.8.0" />
|
||||
<PackageVersion Include="WmiLight" Version="6.14.0" />
|
||||
<PackageVersion Include="WPF-UI" Version="3.0.5" />
|
||||
<PackageVersion Include="WyHash" Version="1.0.5" />
|
||||
<PackageVersion Include="WixToolset.Heat" Version="5.0.2" />
|
||||
|
||||
32
NOTICE.md
32
NOTICE.md
@@ -10,6 +10,7 @@ This software incorporates material from third parties.
|
||||
- Installer/Runner
|
||||
- Measure tool
|
||||
- Peek
|
||||
- PowerDisplay
|
||||
- Registry Preview
|
||||
|
||||
## Utility: Color Picker
|
||||
@@ -1519,6 +1520,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## Utility: PowerDisplay
|
||||
|
||||
### Twinkle Tray
|
||||
|
||||
PowerDisplay's DDC/CI implementation references techniques from Twinkle Tray.
|
||||
|
||||
**Source**: https://github.com/xanderfrangos/twinkle-tray
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright © 2020 Xander Frangos
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
@@ -1557,6 +1587,7 @@ SOFTWARE.
|
||||
- NLog.Extensions.Logging
|
||||
- NLog.Schema
|
||||
- OpenAI
|
||||
- Polly.Core
|
||||
- ReverseMarkdown
|
||||
- ScipBe.Common.Office.OneNote
|
||||
- SharpCompress
|
||||
@@ -1569,5 +1600,6 @@ SOFTWARE.
|
||||
- UnitsNet
|
||||
- UTF.Unknown
|
||||
- WinUIEx
|
||||
- WmiLight
|
||||
- WPF-UI
|
||||
- WyHash
|
||||
334
PowerToys.slnx
334
PowerToys.slnx
@@ -17,7 +17,6 @@
|
||||
<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/Display/Display.vcxproj" Id="caba8dfb-823b-4bf2-93ac-3f31984150d9" />
|
||||
<Project Path="src/common/FilePreviewCommon/FilePreviewCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
@@ -55,8 +54,7 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
||||
<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" />
|
||||
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
||||
</Folder>
|
||||
<Folder Name="/common/interop/">
|
||||
<Project Path="src/common/interop/interop-tests/Common.Interop.UnitTests.csproj">
|
||||
@@ -116,8 +114,10 @@
|
||||
<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" />
|
||||
<File Path="version.h" />
|
||||
</Folder>
|
||||
<Folder Name="/DSC/">
|
||||
<Project Path="src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj">
|
||||
@@ -143,7 +143,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">
|
||||
@@ -157,7 +156,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">
|
||||
@@ -168,19 +166,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" />
|
||||
@@ -194,7 +185,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" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/CommandPalette/Built-in Extensions/">
|
||||
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj">
|
||||
@@ -379,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/">
|
||||
@@ -404,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">
|
||||
@@ -427,8 +414,121 @@
|
||||
<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/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49d456d3-f485-45af-8875-45b44f193ddc" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
||||
@@ -439,14 +539,13 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/Tests/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="A1B2C3D4-E5F6-7890-1234-567890ABCDEF" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-1234-567890abcdef" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Hosts/">
|
||||
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
||||
<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/">
|
||||
@@ -465,13 +564,13 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/imageresizer/">
|
||||
<Project Path="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" Id="0b43679e-edfa-4da0-ad30-f4628b308b1b" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
@@ -482,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" />
|
||||
@@ -503,9 +598,6 @@
|
||||
<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" />
|
||||
@@ -673,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/">
|
||||
@@ -684,13 +774,27 @@
|
||||
<Deploy />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib/PowerDisplay.Lib.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/Tests/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/MeasureTool/">
|
||||
<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" />
|
||||
@@ -710,7 +814,6 @@
|
||||
<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" />
|
||||
@@ -740,7 +843,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">
|
||||
@@ -782,14 +884,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">
|
||||
@@ -819,140 +919,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/">
|
||||
@@ -963,7 +934,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">
|
||||
@@ -984,7 +954,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>
|
||||
@@ -1010,7 +979,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/ZoomIt/">
|
||||
<Project Path="src/modules/ZoomIt/ZoomIt/ZoomIt.vcxproj" Id="0a84f764-3a88-44cd-aa96-41bdbd48627b" />
|
||||
<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="/settings-ui/">
|
||||
@@ -1055,37 +1023,35 @@
|
||||
<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/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<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/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>
|
||||
<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" />
|
||||
<Project Path="src/RunnerV2/RunnerV2/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>
|
||||
</Solution>
|
||||
|
||||
@@ -18,13 +18,28 @@ Advanced Paste is a PowerToys module that provides enhanced clipboard pasting wi
|
||||
|
||||
TODO: Add implementation details
|
||||
|
||||
### Paste with AI Preview
|
||||
|
||||
The "Show preview" setting (`ShowCustomPreview`) controls whether AI-generated results are displayed in a preview window before pasting. **The preview feature does not consume additional AI credits**—the preview displays the same AI response that was already generated, cached locally from a single API call.
|
||||
|
||||
The implementation flow:
|
||||
1. User initiates "Paste with AI" action
|
||||
2. A single AI API call is made via `ExecutePasteFormatAsync`
|
||||
3. The result is cached in `GeneratedResponses`
|
||||
4. If preview is enabled, the cached result is displayed in the preview UI
|
||||
5. User can paste the cached result without any additional API calls
|
||||
|
||||
See the `ExecutePasteFormatAsync(PasteFormat, PasteActionSource)` method in `OptionsViewModel.cs` for the implementation.
|
||||
|
||||
## Debugging
|
||||
|
||||
TODO: Add debugging information
|
||||
|
||||
## Settings
|
||||
|
||||
TODO: Add settings documentation
|
||||
| Setting | Description |
|
||||
|---------|-------------|
|
||||
| `ShowCustomPreview` | When enabled, shows AI-generated results in a preview window before pasting. Does not affect AI credit consumption. |
|
||||
|
||||
## Future Improvements
|
||||
|
||||
|
||||
1616
doc/devdocs/modules/powerdisplay/design.md
Normal file
1616
doc/devdocs/modules/powerdisplay/design.md
Normal file
File diff suppressed because it is too large
Load Diff
223
doc/devdocs/modules/powerdisplay/mccsParserDesign.md
Normal file
223
doc/devdocs/modules/powerdisplay/mccsParserDesign.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# MCCS Capabilities String Parser - Recursive Descent Design
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the recursive descent parser implementation for DDC/CI MCCS (Monitor Control Command Set) capabilities strings.
|
||||
|
||||
### Attention!
|
||||
This document and the code implement are generated by Copilot.
|
||||
|
||||
## Grammar Definition (BNF)
|
||||
|
||||
```bnf
|
||||
capabilities ::= ['('] segment* [')']
|
||||
segment ::= identifier '(' segment_content ')'
|
||||
segment_content ::= text | vcp_entries | hex_list
|
||||
vcp_entries ::= vcp_entry*
|
||||
vcp_entry ::= hex_byte [ '(' hex_list ')' ]
|
||||
hex_list ::= hex_byte*
|
||||
hex_byte ::= [0-9A-Fa-f]{2}
|
||||
identifier ::= [a-z_A-Z]+
|
||||
text ::= [^()]+
|
||||
```
|
||||
|
||||
## Example Input
|
||||
|
||||
```
|
||||
(prot(monitor)type(lcd)model(PD3220U)cmds(01 02 03 07)vcp(10 12 14(04 05 06) 16 60(11 12 0F) DC DF)mccs_ver(2.2)vcpname(F0(Custom Setting)))
|
||||
```
|
||||
|
||||
## Parser Architecture
|
||||
|
||||
### Component Hierarchy
|
||||
|
||||
```
|
||||
MccsCapabilitiesParser (main parser)
|
||||
├── ParseCapabilities() → MccsParseResult
|
||||
├── ParseSegment() → ParsedSegment?
|
||||
├── ParseBalancedContent() → string
|
||||
├── ParseIdentifier() → ReadOnlySpan<char>
|
||||
├── ApplySegment() → void
|
||||
│ ├── ParseHexList() → List<byte>
|
||||
│ ├── ParseVcpEntries() → Dictionary<byte, VcpCodeInfo>
|
||||
│ └── ParseVcpNames() → void
|
||||
│
|
||||
├── VcpEntryParser (sub-parser for vcp() content)
|
||||
│ └── TryParseEntry() → VcpEntry
|
||||
│
|
||||
├── VcpNameParser (sub-parser for vcpname() content)
|
||||
│ └── TryParseEntry() → (byte code, string name)
|
||||
│
|
||||
└── WindowParser (sub-parser for windowN() content)
|
||||
├── Parse() → WindowCapability
|
||||
└── ParseSubSegment() → (name, content)?
|
||||
```
|
||||
|
||||
### Design Principles
|
||||
|
||||
1. **ref struct for Zero Allocation**
|
||||
- Main parser uses `ref struct` to avoid heap allocation
|
||||
- Works with `ReadOnlySpan<char>` for efficient string slicing
|
||||
- No intermediate string allocations during parsing
|
||||
|
||||
2. **Recursive Descent Pattern**
|
||||
- Each grammar rule has a corresponding parse method
|
||||
- Methods call each other recursively for nested structures
|
||||
- Single-character lookahead via `Peek()`
|
||||
|
||||
3. **Error Recovery**
|
||||
- Errors are accumulated, not thrown
|
||||
- Parser attempts to continue after errors
|
||||
- Returns partial results when possible
|
||||
|
||||
4. **Sub-parsers for Specialized Content**
|
||||
- `VcpEntryParser` for VCP code entries
|
||||
- `VcpNameParser` for custom VCP names
|
||||
- Each sub-parser handles its own grammar subset
|
||||
|
||||
## Parse Methods Detail
|
||||
|
||||
### ParseCapabilities()
|
||||
Entry point. Handles optional outer parentheses and iterates through segments.
|
||||
|
||||
```csharp
|
||||
private MccsParseResult ParseCapabilities()
|
||||
{
|
||||
// Handle optional outer parens
|
||||
// while (!IsAtEnd()) { ParseSegment() }
|
||||
// Return result with accumulated errors
|
||||
}
|
||||
```
|
||||
|
||||
### ParseSegment()
|
||||
Parses a single `identifier(content)` segment.
|
||||
|
||||
```csharp
|
||||
private ParsedSegment? ParseSegment()
|
||||
{
|
||||
// 1. ParseIdentifier()
|
||||
// 2. Expect '('
|
||||
// 3. ParseBalancedContent()
|
||||
// 4. Expect ')'
|
||||
}
|
||||
```
|
||||
|
||||
### ParseBalancedContent()
|
||||
Extracts content between balanced parentheses, handling nested parens.
|
||||
|
||||
```csharp
|
||||
private string ParseBalancedContent()
|
||||
{
|
||||
int depth = 1;
|
||||
while (depth > 0) {
|
||||
if (char == '(') depth++;
|
||||
if (char == ')') depth--;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ParseVcpEntries()
|
||||
Delegates to `VcpEntryParser` for the specialized VCP entry grammar.
|
||||
|
||||
```csharp
|
||||
vcp_entry ::= hex_byte [ '(' hex_list ')' ]
|
||||
|
||||
Examples:
|
||||
- "10" → code=0x10, values=[]
|
||||
- "14(04 05 06)" → code=0x14, values=[4, 5, 6]
|
||||
- "60(11 12 0F)" → code=0x60, values=[0x11, 0x12, 0x0F]
|
||||
```
|
||||
|
||||
## Comparison with Other Approaches
|
||||
|
||||
| Approach | Pros | Cons |
|
||||
|----------|------|------|
|
||||
| **Recursive Descent** (this) | Clear structure, handles nesting, extensible | More code |
|
||||
| **Regex** (DDCSharp) | Concise | Hard to debug, limited nesting |
|
||||
| **Mixed** (original) | Pragmatic | Inconsistent, hard to maintain |
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
- **Time Complexity**: O(n) where n = input length
|
||||
- **Space Complexity**: O(1) for parsing + O(m) for output where m = number of VCP codes
|
||||
- **Allocations**: Minimal - only for output structures
|
||||
|
||||
## Supported Segments
|
||||
|
||||
| Segment | Description | Parser |
|
||||
|---------|-------------|--------|
|
||||
| `prot(...)` | Protocol type | Direct assignment |
|
||||
| `type(...)` | Display type (lcd/crt) | Direct assignment |
|
||||
| `model(...)` | Model name | Direct assignment |
|
||||
| `cmds(...)` | Supported commands | ParseHexList |
|
||||
| `vcp(...)` | VCP code entries | VcpEntryParser |
|
||||
| `mccs_ver(...)` | MCCS version | Direct assignment |
|
||||
| `vcpname(...)` | Custom VCP names | VcpNameParser |
|
||||
| `windowN(...)` | PIP/PBP window capabilities | WindowParser |
|
||||
|
||||
### Window Segment Format
|
||||
|
||||
The `windowN` segment (where N is 1, 2, 3, etc.) describes PIP/PBP window capabilities:
|
||||
|
||||
```
|
||||
window1(type(PIP) area(25 25 1895 1175) max(640 480) min(10 10) window(10))
|
||||
```
|
||||
|
||||
| Sub-field | Format | Description |
|
||||
|-----------|--------|-------------|
|
||||
| `type` | `type(PIP)` or `type(PBP)` | Window type (Picture-in-Picture or Picture-by-Picture) |
|
||||
| `area` | `area(x1 y1 x2 y2)` | Window area coordinates in pixels |
|
||||
| `max` | `max(width height)` | Maximum window dimensions |
|
||||
| `min` | `min(width height)` | Minimum window dimensions |
|
||||
| `window` | `window(id)` | Window identifier |
|
||||
|
||||
All sub-fields are optional; missing fields default to zero values.
|
||||
|
||||
## Error Handling
|
||||
|
||||
```csharp
|
||||
public readonly struct ParseError
|
||||
{
|
||||
public int Position { get; } // Character position
|
||||
public string Message { get; } // Human-readable error
|
||||
}
|
||||
|
||||
public sealed class MccsParseResult
|
||||
{
|
||||
public VcpCapabilities Capabilities { get; }
|
||||
public IReadOnlyList<ParseError> Errors { get; }
|
||||
public bool HasErrors => Errors.Count > 0;
|
||||
public bool IsValid => !HasErrors && Capabilities.SupportedVcpCodes.Count > 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
```csharp
|
||||
// Parse capabilities string
|
||||
var result = MccsCapabilitiesParser.Parse(capabilitiesString);
|
||||
|
||||
if (result.IsValid)
|
||||
{
|
||||
var caps = result.Capabilities;
|
||||
Console.WriteLine($"Model: {caps.Model}");
|
||||
Console.WriteLine($"MCCS Version: {caps.MccsVersion}");
|
||||
Console.WriteLine($"VCP Codes: {caps.SupportedVcpCodes.Count}");
|
||||
}
|
||||
|
||||
if (result.HasErrors)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
Console.WriteLine($"Parse error at {error.Position}: {error.Message}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Edge Cases Handled
|
||||
|
||||
1. **Missing outer parentheses** (Apple Cinema Display)
|
||||
2. **No spaces between hex bytes** (`010203` vs `01 02 03`)
|
||||
3. **Nested parentheses** in VCP values
|
||||
4. **Unknown segments** (logged but not fatal)
|
||||
5. **Malformed input** (partial results returned)
|
||||
@@ -1549,7 +1549,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
processes.resize(bytes / sizeof(processes[0]));
|
||||
|
||||
std::array<std::wstring_view, 44> processesToTerminate = {
|
||||
std::array<std::wstring_view, 45> processesToTerminate = {
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.Settings.exe",
|
||||
L"PowerToys.AdvancedPaste.exe",
|
||||
@@ -1565,6 +1565,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.PowerRename.exe",
|
||||
L"PowerToys.ImageResizer.exe",
|
||||
L"PowerToys.LightSwitchService.exe",
|
||||
L"PowerToys.PowerDisplay.exe",
|
||||
L"PowerToys.GcodeThumbnailProvider.exe",
|
||||
L"PowerToys.BgcodeThumbnailProvider.exe",
|
||||
L"PowerToys.PdfThumbnailProvider.exe",
|
||||
|
||||
@@ -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
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
29
installer/PowerToysSetupVNext/PowerDisplay.wxs
Normal file
29
installer/PowerToysSetupVNext/PowerDisplay.wxs
Normal file
@@ -0,0 +1,29 @@
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||
xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define PowerDisplayAssetsFiles=?>
|
||||
<?define PowerDisplayAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\PowerDisplay?>
|
||||
|
||||
<Fragment>
|
||||
<!-- Power Display -->
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="PowerDisplayAssetsInstallFolder" Name="PowerDisplay" />
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="PowerDisplayAssetsInstallFolder" FileSource="$(var.PowerDisplayAssetsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--PowerDisplayAssetsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="PowerDisplayComponentGroup">
|
||||
<Component Id="RemovePowerDisplayFolder" Guid="B8F2E3A5-72C1-4A2D-9B3F-8E5D7C6A4F9B" Directory="PowerDisplayAssetsInstallFolder" >
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemovePowerDisplayFolder" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderPowerDisplayAssetsFolder" Directory="PowerDisplayAssetsInstallFolder" On="uninstall"/>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -47,6 +47,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\NewPlus.wxs.bk ..\..\..\NewPlus.wxs
|
||||
call move /Y ..\..\..\Peek.wxs.bk ..\..\..\Peek.wxs
|
||||
call move /Y ..\..\..\PowerRename.wxs.bk ..\..\..\PowerRename.wxs
|
||||
call move /Y ..\..\..\PowerDisplay.wxs.bk ..\..\..\PowerDisplay.wxs
|
||||
call move /Y ..\..\..\Product.wxs.bk ..\..\..\Product.wxs
|
||||
call move /Y ..\..\..\RegistryPreview.wxs.bk ..\..\..\RegistryPreview.wxs
|
||||
call move /Y ..\..\..\Resources.wxs.bk ..\..\..\Resources.wxs
|
||||
@@ -123,6 +124,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Compile Include="KeyboardManager.wxs" />
|
||||
<Compile Include="Peek.wxs" />
|
||||
<Compile Include="PowerRename.wxs" />
|
||||
<Compile Include="PowerDisplay.wxs" />
|
||||
<Compile Include="DscResources.wxs" />
|
||||
<Compile Include="RegistryPreview.wxs" />
|
||||
<Compile Include="Run.wxs" />
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<ComponentGroupRef Id="LightSwitchComponentGroup" />
|
||||
<ComponentGroupRef Id="PeekComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerRenameComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerDisplayComponentGroup" />
|
||||
<ComponentGroupRef Id="RegistryPreviewComponentGroup" />
|
||||
<ComponentGroupRef Id="RunComponentGroup" />
|
||||
<ComponentGroupRef Id="SettingsComponentGroup" />
|
||||
|
||||
@@ -367,6 +367,12 @@
|
||||
</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">
|
||||
<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" />
|
||||
</Component>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?undef CompGUIDPrefix?>
|
||||
<?endforeach?>
|
||||
|
||||
@@ -176,6 +176,10 @@ Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PS
|
||||
Generate-FileList -fileDepsJson "" -fileListName LightSwitchFiles -wxsFilePath $PSScriptRoot\LightSwitch.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\LightSwitchService"
|
||||
Generate-FileComponents -fileListName "LightSwitchFiles" -wxsFilePath $PSScriptRoot\LightSwitch.wxs
|
||||
|
||||
#PowerDisplay
|
||||
Generate-FileList -fileDepsJson "" -fileListName PowerDisplayAssetsFiles -wxsFilePath $PSScriptRoot\PowerDisplay.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerDisplay"
|
||||
Generate-FileComponents -fileListName "PowerDisplayAssetsFiles" -wxsFilePath $PSScriptRoot\PowerDisplay.wxs
|
||||
|
||||
#New+
|
||||
Generate-FileList -fileDepsJson "" -fileListName NewPlusAssetsFiles -wxsFilePath $PSScriptRoot\NewPlus.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\NewPlus"
|
||||
Generate-FileComponents -fileListName "NewPlusAssetsFiles" -wxsFilePath $PSScriptRoot\NewPlus.wxs
|
||||
|
||||
@@ -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="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)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>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\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="..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</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('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</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"
|
||||
|
||||
11
src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj
Normal file
11
src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj
Normal file
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
119
src/PowerToys.ActionRunner/Program.cs
Normal file
119
src/PowerToys.ActionRunner/Program.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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.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/RunnerV2/RunnerV2/Assets/PowerToysDark.ico
Normal file
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysDark.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysLight.ico
Normal file
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysLight.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
17
src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs
Normal file
17
src/RunnerV2/RunnerV2/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);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/RunnerV2/RunnerV2/Helpers/COMUtils.cs
Normal file
57
src/RunnerV2/RunnerV2/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);
|
||||
}
|
||||
}
|
||||
}
|
||||
218
src/RunnerV2/RunnerV2/Helpers/CentralizedKeyboardHookManager.cs
Normal file
218
src/RunnerV2/RunnerV2/Helpers/CentralizedKeyboardHookManager.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
// 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 ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Windows.System;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class CentralizedKeyboardHookManager
|
||||
{
|
||||
private static readonly UIntPtr _ignoreKeyEventFlag = 0x5555;
|
||||
|
||||
private static readonly Dictionary<string, List<(HotkeySettings HotkeySettings, Action Action)>> _keyboardHooks = [];
|
||||
|
||||
private static HotkeySettingsControlHook _hotkeySettingsControlHook = new(OnKeyDown, OnKeyUp, IsActive, (_, specialFlags) => specialFlags != _ignoreKeyEventFlag);
|
||||
|
||||
private static void OnKeyDown(int key)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private static void OnKeyUp(int key)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
0x25 => true, // VK_LEFT
|
||||
0x26 => true, // VK_UP
|
||||
0x27 => true, // VK_RIGHT
|
||||
0x28 => true, // VK_DOWN
|
||||
0x90 => true, // VK_NUMLOCK
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs
Normal file
93
src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
// 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 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");
|
||||
break;
|
||||
case RestartScheduledMode.RestartElevatedWithOpenSettings:
|
||||
RestartAsAdministrator("--restartedElevated --open-settings");
|
||||
break;
|
||||
case RestartScheduledMode.RestartNonElevated:
|
||||
// Todo: restart unelevated
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/RunnerV2/RunnerV2/Helpers/NotificationHelper.cs
Normal file
52
src/RunnerV2/RunnerV2/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/RunnerV2/RunnerV2/Helpers/PackageHelper.cs
Normal file
194
src/RunnerV2/RunnerV2/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/RunnerV2/RunnerV2/Helpers/ProcessHelper.cs
Normal file
30
src/RunnerV2/RunnerV2/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();
|
||||
}
|
||||
}
|
||||
}
|
||||
99
src/RunnerV2/RunnerV2/Helpers/QuickAccessHelper.cs
Normal file
99
src/RunnerV2/RunnerV2/Helpers/QuickAccessHelper.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
// 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;
|
||||
|
||||
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);
|
||||
quickAccessIpc.Start();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return !_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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
226
src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs
Normal file
226
src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using Update;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides helper methods to interact with the PowerToys Settings window.
|
||||
/// </summary>
|
||||
internal static class SettingsHelper
|
||||
{
|
||||
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)
|
||||
{
|
||||
JsonDocument messageDocument = JsonDocument.Parse(message);
|
||||
|
||||
foreach (var property in messageDocument.RootElement.EnumerateObject())
|
||||
{
|
||||
switch (property.Name)
|
||||
{
|
||||
case "action":
|
||||
foreach (var moduleName in property.Value.EnumerateObject())
|
||||
{
|
||||
_settingsUtils.SaveSettings(moduleName.Value.ToString(), moduleName.Name);
|
||||
if (moduleName.Name == "general")
|
||||
{
|
||||
switch (moduleName.Value.GetProperty("action_name").GetString())
|
||||
{
|
||||
case "restart_elevation":
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevatedWithOpenSettings;
|
||||
Runner.Close();
|
||||
break;
|
||||
case "restart_mentain_elevation":
|
||||
// Todo:
|
||||
break;
|
||||
case "check_for_updates":
|
||||
UpdateSettingsHelper.TriggerUpdateCheck();
|
||||
break;
|
||||
case "request_update_state_date":
|
||||
// Todo:
|
||||
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? action))
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
action();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "get_all_hotkey_conflicts":
|
||||
// Todo: Handle hotkey conflict
|
||||
break;
|
||||
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())
|
||||
{
|
||||
try
|
||||
{
|
||||
_settingsUtils.SaveSettings(powertoysSettingsPart.Value.ToString(), powertoysSettingsPart.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed writing {powertoysSettingsPart.Name} settings from Settings window", ex);
|
||||
}
|
||||
|
||||
if (Runner.LoadedModules.Find(m => m.Name == powertoysSettingsPart.Name) is IPowerToysModuleSettingsChangedSubscriber module && module is IPowerToysModule ptModule && ptModule.Enabled)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
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)
|
||||
{
|
||||
settingsChangedSubscriber.OnSettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.PostMessageW(Runner.RunnerHwnd, (uint)NativeMethods.WindowMessages.REFRESH_SETTINGS, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"Unknown message received from Settings: {property.Name}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseSettingsWindow()
|
||||
{
|
||||
using var closeEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerToysRunnerTerminateSettingsEvent());
|
||||
closeEventWrapper.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
208
src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs
Normal file
208
src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
// 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.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
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/PowerToysDark.ico" : "./Assets/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,
|
||||
}
|
||||
|
||||
private static bool _doubleClickTimerRunning;
|
||||
private static bool _doubleClickDetected;
|
||||
|
||||
private static IntPtr _trayIconMenu;
|
||||
|
||||
static TrayIconManager()
|
||||
{
|
||||
_trayIconMenu = CreatePopupMenu();
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Settings), "Settings\tDouble-click");
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Documentation), "Documentation");
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.ReportBug), "Report a Bug");
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Close), "Close");
|
||||
new ThemeListener().ThemeChanged += (_) =>
|
||||
{
|
||||
PostMessageW(Runner.RunnerHwnd, 0x0800, IntPtr.Zero, 0x9000);
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsBugReportToolRunning { get; set; }
|
||||
|
||||
internal static void ProcessTrayMenuCommand(nuint commandId)
|
||||
{
|
||||
switch ((TrayButton)commandId)
|
||||
{
|
||||
case TrayButton.Settings:
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/RunnerV2/RunnerV2/Models/IPowerToysModule.cs
Normal file
47
src/RunnerV2/RunnerV2/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; }
|
||||
}
|
||||
}
|
||||
@@ -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> 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();
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
169
src/RunnerV2/RunnerV2/Models/ProcessModuleAbstractClass.cs
Normal file
169
src/RunnerV2/RunnerV2/Models/ProcessModuleAbstractClass.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
// 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 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>
|
||||
/// 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; }
|
||||
|
||||
/// <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;
|
||||
|
||||
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/RunnerV2/RunnerV2/Models/RegistryChangeSet.cs
Normal file
45
src/RunnerV2/RunnerV2/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/RunnerV2/RunnerV2/Models/RegistryValueChange.cs
Normal file
124
src/RunnerV2/RunnerV2/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/RunnerV2/RunnerV2/Models/SpecialMode.cs
Normal file
16
src/RunnerV2/RunnerV2/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,
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
// 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
|
||||
{
|
||||
Scope = Microsoft.Win32.RegistryHive.LocalMachine,
|
||||
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
|
||||
{
|
||||
Scope = Microsoft.Win32.RegistryHive.LocalMachine,
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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(() =>
|
||||
{
|
||||
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();
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 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);
|
||||
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,38 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
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
|
||||
{
|
||||
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 void Disable()
|
||||
{
|
||||
using var terminateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminateKBMSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class MouseHighlighterModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MouseHighlighter";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseHighlighter;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
DisableMouseHighlighter();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
EnableMouseHighlighter();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<MouseHighlighterSettings>(Name).Properties.ActivationShortcut, ToggleMouseHighlighter));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
MouseHighlighterSettingsChanged();
|
||||
}
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void DisableMouseHighlighter();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void EnableMouseHighlighter();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void MouseHighlighterSettingsChanged();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void ToggleMouseHighlighter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 MouseJumpModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MouseJump";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseJump;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseJumpEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.MouseJumpUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MouseJumpUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.TerminateMouseJumpSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseJumpSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.ActivationShortcut, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeMouseJumpEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.MouseJumpShowPreviewEvent());
|
||||
invokeMouseJumpEvent.Set();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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 partial class MousePointerCrosshairsModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MousePointerCrosshairs";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MousePointerCrosshairs;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
DisableMousePointerCrosshairs();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
EnableMousePointerCrosshairs();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<MousePointerCrosshairsSettings>(Name).Properties;
|
||||
Shortcuts.Add((settings.ActivationShortcut, OnMousePointerCrosshairsActivationShortcut));
|
||||
Shortcuts.Add((settings.GlidingCursorActivationShortcut, OnMousePointerCrosshairsGlidingCursorShortcut));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
OnMousePointerCrosshairsSettingsChanged();
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void DisableMousePointerCrosshairs();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void EnableMousePointerCrosshairs();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsSettingsChanged();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsActivationShortcut();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsGlidingCursorShortcut();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
// 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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceProcess;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class MouseWithoutBordersModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleSettingsChangedSubscriber, IPowerToysModuleCustomActionsProvider
|
||||
{
|
||||
public string Name => "MouseWithoutBorders";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseWithoutBorders;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.MouseWithoutBorders.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MouseWithoutBorders";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public override string ProcessArguments
|
||||
{
|
||||
get
|
||||
{
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseWithoutBordersSettings>();
|
||||
return settings.Properties.UseService ? " UseService" : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, Action> CustomActions => new Dictionary<string, Action>
|
||||
{
|
||||
{ "add_firewall", LaunchAddFirewallProcess },
|
||||
{ "uninstall_service", () => { new Thread(UnregisterService).Start(); } },
|
||||
};
|
||||
|
||||
private void RegisterService()
|
||||
{
|
||||
IntPtr schSCManager = NativeMethods.OpenSCManagerW(string.Empty, "ServicesActive", NativeMethods.SCMANAGERALLACCESS);
|
||||
if (schSCManager == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open Service Control Manager");
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr hService = NativeMethods.OpenServiceW(schSCManager, "PowerToys.MWB.Service", 0x0004 | 0x0001 | 0x0002);
|
||||
|
||||
string servicePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "PowerToys.MouseWithoutBordersService.exe");
|
||||
|
||||
IntPtr pServiceConfig = IntPtr.Zero;
|
||||
if (!NativeMethods.QueryServiceConfigW(hService, IntPtr.Zero, 0, out uint bytesNeeded))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == 122)
|
||||
{
|
||||
pServiceConfig = Marshal.AllocHGlobal((int)bytesNeeded);
|
||||
if (!NativeMethods.QueryServiceConfigW(hService, pServiceConfig, bytesNeeded, out _))
|
||||
{
|
||||
Marshal.FreeHGlobal(pServiceConfig);
|
||||
pServiceConfig = IntPtr.Zero;
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool alreadyRegistered = false;
|
||||
bool isServicePathCorrect = true;
|
||||
|
||||
string EscapeDoubleQuotes(string input)
|
||||
{
|
||||
StringBuilder output = new(input.Length);
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (c == '"')
|
||||
{
|
||||
output.Append('\\');
|
||||
}
|
||||
|
||||
output.Append(c);
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
string expectedPath = "\"" + servicePath + "\" " + EscapeDoubleQuotes(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
|
||||
|
||||
if (pServiceConfig != IntPtr.Zero)
|
||||
{
|
||||
alreadyRegistered = true;
|
||||
var serviceConfig = Marshal.PtrToStructure<NativeMethods.QueryServiceConfig>(pServiceConfig);
|
||||
string currentPath = serviceConfig.lpBinaryPathName;
|
||||
|
||||
if (currentPath != expectedPath)
|
||||
{
|
||||
Logger.LogInfo($"MWB Service path is incorrect. Current: {currentPath} Expected: {expectedPath}");
|
||||
}
|
||||
|
||||
if (serviceConfig.dwStartType == 0x0004)
|
||||
{
|
||||
if (!NativeMethods.ChangeServiceConfigW(hService, 0xffffffff, 0x3, 0xffffffff, null!, null!, IntPtr.Zero, null!, null!, null!, null!))
|
||||
{
|
||||
// Check if marked for delete
|
||||
if (Marshal.GetLastWin32Error() == 1072)
|
||||
{
|
||||
alreadyRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(pServiceConfig);
|
||||
}
|
||||
|
||||
if (alreadyRegistered)
|
||||
{
|
||||
if (!isServicePathCorrect)
|
||||
{
|
||||
if (!NativeMethods.ChangeServiceConfigW(hService, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, expectedPath, null!, IntPtr.Zero, null!, null!, null!, null!))
|
||||
{
|
||||
Logger.LogError("Couldn't update MWB Service path");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInfo("MWB Service path updated successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hService = NativeMethods.CreateServiceW(
|
||||
schSCManager,
|
||||
"PowerToys.MWB.Service",
|
||||
"PowerToys.MWB.Service",
|
||||
NativeMethods.SERVICEALLACCESS,
|
||||
0x00000010,
|
||||
0x00000003,
|
||||
0x00000001,
|
||||
expectedPath,
|
||||
null!,
|
||||
IntPtr.Zero,
|
||||
null!,
|
||||
null!,
|
||||
null!);
|
||||
|
||||
if (hService == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't create MWB Service");
|
||||
return;
|
||||
}
|
||||
|
||||
string sid = WindowsIdentity.GetCurrent().User!.Value;
|
||||
|
||||
string securityDescriptor = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWPDTLO;;;"
|
||||
+ sid
|
||||
+ ")S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)";
|
||||
|
||||
if (!NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptorW(securityDescriptor, 1, out nint pSD, out uint szSD))
|
||||
{
|
||||
Logger.LogError("Couldn't convert security descriptor string to security descriptor");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NativeMethods.SetServiceObjectSecurity(hService, 4, pSD))
|
||||
{
|
||||
Logger.LogError("Couldn't set MWB Service security descriptor");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.CloseServiceHandle(schSCManager);
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
|
||||
private void UnregisterService()
|
||||
{
|
||||
IntPtr schSCManager = NativeMethods.OpenSCManagerW(string.Empty, "ServicesActive", NativeMethods.SCMANAGERALLACCESS);
|
||||
if (schSCManager == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open Service Control Manager");
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr hService = NativeMethods.OpenServiceW(schSCManager, "PowerToys.MWB.Service", 0x0020 | 0x10000);
|
||||
|
||||
if (hService == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open MWB Service");
|
||||
return;
|
||||
}
|
||||
|
||||
NativeMethods.ServiceStatus status = default;
|
||||
if (NativeMethods.ControlService(hService, 0x0001, ref status))
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
while (NativeMethods.QueryServiceStatusW(hService, ref status))
|
||||
{
|
||||
if (status.dwCurrentState == 0x0003)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outer:
|
||||
bool deleteResult = NativeMethods.DeleteService(hService);
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
|
||||
if (!deleteResult)
|
||||
{
|
||||
Logger.LogError("Couldn't delete MWB Service");
|
||||
}
|
||||
}
|
||||
|
||||
private void LaunchAddFirewallProcess()
|
||||
{
|
||||
string args = "/S /c \"" +
|
||||
"echo \"Deleting existing inbound firewall rules for PowerToys.MouseWithoutBorders.exe\"" +
|
||||
" & netsh advfirewall firewall delete rule dir=in name=all program=\"" +
|
||||
"\\PowerToys.MouseWithoutBorders.exe" +
|
||||
"\" & echo \"Adding an inbound firewall rule for PowerToys.MouseWithoutBorders.exe\"" +
|
||||
" & netsh advfirewall firewall add rule name=\"PowerToys.MouseWithoutBorders\" dir=in action=allow program=\"" +
|
||||
"\\PowerToys.MouseWithoutBorders.exe" +
|
||||
"\" enable=yes remoteip=any profile=any protocol=tcp & pause\"";
|
||||
|
||||
new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
Arguments = args,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
Verb = "runas",
|
||||
FileName = "cmd.exe",
|
||||
},
|
||||
}.Start();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
var services = Process.GetProcessesByName("PowerToys.MouseWithoutBordersService");
|
||||
services = [..services, ..Process.GetProcessesByName("PowerToys.MouseWithoutBorders"), ..Process.GetProcessesByName("PowerToys.MouseWithoutBordersHelper")];
|
||||
|
||||
foreach (var service in services)
|
||||
{
|
||||
try
|
||||
{
|
||||
service.Kill();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to kill process.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
private bool _runInServiceMode;
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseWithoutBordersSettings>(Name).Properties;
|
||||
|
||||
bool newRunInServiceMode = settings.UseService && GPOWrapper.GetConfiguredMwbAllowServiceModeValue() != GpoRuleConfigured.Disabled;
|
||||
|
||||
if (newRunInServiceMode == _runInServiceMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_runInServiceMode = newRunInServiceMode;
|
||||
Disable();
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
if (_runInServiceMode)
|
||||
{
|
||||
RegisterService();
|
||||
}
|
||||
else
|
||||
{
|
||||
var processes = Process.GetProcessesByName("PowerToys.MouseWithoutBordersService");
|
||||
foreach (var p in processes)
|
||||
{
|
||||
bool stopped = false;
|
||||
do
|
||||
{
|
||||
stopped = p.HasExited;
|
||||
}
|
||||
while (!stopped);
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
LaunchProcess();
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class NewPlusModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "NewPlus";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.NewPlus;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredNewPlusEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateNewPlusRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateNewPlusRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "NewPlusPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.NewPlus.ShellExtension.dll")]
|
||||
private static partial void UpdateNewPlusRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class PeekModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
private static readonly nint PeekDllHandle = LoadPeekDll();
|
||||
|
||||
private static nint LoadPeekDll()
|
||||
{
|
||||
// Pin the DLL in memory for the life of the Runner process, because it owns WinEvent hook callbacks.
|
||||
var dllPath = Path.Combine(AppContext.BaseDirectory, "WinUI3Apps", "PowerToys.Peek.dll");
|
||||
return NativeLibrary.Load(dllPath);
|
||||
}
|
||||
|
||||
private readonly EventWaitHandle terminatePeekEvent = new(false, EventResetMode.AutoReset, Constants.TerminatePeekEvent());
|
||||
|
||||
public string Name => "Peek";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Peek;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPeekEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.Peek.UI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Peek.UI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
terminatePeekEvent.Set();
|
||||
PeekSetForegroundHookActive(false);
|
||||
PeekManageSpaceModeHook();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
terminatePeekEvent.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Todo: Implement always launch non-elevated
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<PeekSettings>(Name).Properties;
|
||||
HotkeySettings hotkey = settings.EnableSpaceToActivate.Value ? new HotkeySettings(false, false, false, false, 0x20) : settings.DefaultActivationShortcut;
|
||||
Shortcuts.Add((hotkey, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
|
||||
PeekOnHotkey();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
PeekSetForegroundHookActive(SettingsUtils.Default.GetSettings<PeekSettings>(Name).Properties.EnableSpaceToActivate.Value);
|
||||
PeekManageSpaceModeHook();
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool PeekOnHotkey();
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
private static partial void PeekSetForegroundHookActive([MarshalAs(UnmanagedType.Bool)] bool active);
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
private static partial void PeekManageSpaceModeHook();
|
||||
}
|
||||
}
|
||||
@@ -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 PowerAccentModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "PowerAccent";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.PowerAccent;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredQuickAccentEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.PowerAccent.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerAccent";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerDisplayModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IDisposable
|
||||
{
|
||||
public string Name => "PowerDisplay";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerDisplay;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerDisplayEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.PowerDisplay.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerDisplay.exe";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
private static readonly string _outputPipeName = "powertoys_power_display_" + Guid.NewGuid();
|
||||
private readonly TwoWayPipeMessageIPCManaged _ipc = new("\\\\.\\pipe\\powertoys_power_display_input", "\\\\.\\pipe\\" + _outputPipeName, (_) => { });
|
||||
|
||||
public override string ProcessArguments => _outputPipeName;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_ipc.Send(Constants.PowerDisplayTerminateAppMessage());
|
||||
_ipc.End();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
_ipc.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ipc.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public Dictionary<string, Action> CustomActions => new()
|
||||
{
|
||||
{ "Launch", () => { _ipc.Send(Constants.PowerDisplayToggleMessage()); } },
|
||||
{ "RefreshMonitors", () => { _ipc.Send(Constants.RefreshPowerDisplayMonitorsEvent()); } },
|
||||
{ "ApplyProfile", () => { _ipc.Send(Constants.PowerDisplayApplyProfileMessage()); } },
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 PowerOCRModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "TextExtractor";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerOcr;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredTextExtractorEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.PowerOCR.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerOCR";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<PowerOcrSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
using var invokeOcrEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent());
|
||||
invokeOcrEvent.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminatePowerOCRSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 PowerRenameModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "PowerRename";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerRename;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerRenameEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdatePowerRenameRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdatePowerRenameRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "PowerRenameContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.PowerRenameExt.dll")]
|
||||
private static partial void UpdatePowerRenameRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -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 System.IO;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerToysRunModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
public string Name => "PowerToys Run";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerLauncher;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
|
||||
|
||||
public override string ProcessPath => Path.GetFullPath("PowerToys.PowerLauncher.exe");
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerLauncher";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.ElevateIfApplicable | ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public override string ProcessArguments => $"-powerToysPid {Environment.ProcessId}";
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.RunExitEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts =>
|
||||
[
|
||||
(
|
||||
SettingsUtils.Default.GetSettings<PowerLauncherSettings>(Name).Properties.OpenPowerLauncher,
|
||||
() =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeRunEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.PowerLauncherCentralizedHookSharedEvent());
|
||||
invokeRunEvent.Set();
|
||||
}
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.Win32;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class RegistryPreviewModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.RegistryPreview;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
|
||||
|
||||
public string Name => "RegistryPreview";
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.RegistryPreview.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.RegistryPreview";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (!RegistryPreviewChangeSet.UnApplyIfApplied())
|
||||
{
|
||||
Logger.LogError("Unapplying registry changes failed");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
bool defaultRegApp = SettingsUtils.Default.GetSettings<RegistryPreviewSettings>(Name).Properties.DefaultRegApp;
|
||||
if (defaultRegApp && !RegistryPreviewSetDefaultAppChangeSet.IsApplied)
|
||||
{
|
||||
if (!RegistryPreviewSetDefaultAppChangeSet.Apply())
|
||||
{
|
||||
Logger.LogError("Applying reg default handler failed.");
|
||||
}
|
||||
|
||||
NativeMethods.SHChangeNotify(NativeMethods.SHCNE_ASSOCCHANGED, NativeMethods.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
else if (!defaultRegApp && RegistryPreviewSetDefaultAppChangeSet.IsApplied)
|
||||
{
|
||||
if (RegistryPreviewSetDefaultAppChangeSet.UnApply())
|
||||
{
|
||||
Logger.LogError("Unapplying reg default handler failed.");
|
||||
}
|
||||
|
||||
NativeMethods.SHChangeNotify(NativeMethods.SHCNE_ASSOCCHANGED, NativeMethods.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
if (!RegistryPreviewChangeSet.ApplyIfNotApplied())
|
||||
{
|
||||
Logger.LogError("Applying registry changes failed");
|
||||
}
|
||||
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
public Dictionary<string, Action> CustomActions
|
||||
{
|
||||
get => new() { { "Launch", () => LaunchProcess() } };
|
||||
}
|
||||
|
||||
private RegistryChangeSet RegistryPreviewSetDefaultAppChangeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
string installationDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
string appName = "Registry Preview";
|
||||
string registryKeyPrefix = "Software\\Classes\\";
|
||||
RegistryValueChange[] changes =
|
||||
[
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\Application",
|
||||
KeyName = "ApplicationName",
|
||||
Value = appName,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\DefaultIcon",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\shell\\open\\command",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe \"----ms-protocol:ms-encodedlaunch:App?ContractId=Windows.File&Verb=open&File=%1\"",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ".reg\\OpenWithProgIDs",
|
||||
KeyName = null,
|
||||
Value = ProcessName,
|
||||
}
|
||||
];
|
||||
return new RegistryChangeSet { Changes = changes };
|
||||
}
|
||||
}
|
||||
|
||||
private RegistryChangeSet RegistryPreviewChangeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
string installationDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
RegistryValueChange[] changes =
|
||||
[
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = "Software\\Classes\\regfile\\shell\\preview\\command",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe \"%1\"",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = "Software\\Classes\\regfile\\shell\\preview",
|
||||
KeyName = "icon",
|
||||
Value = installationDir + "\\WinUI3Apps\\Assets\\RegistryPreview\\RegistryPreview.ico",
|
||||
}
|
||||
];
|
||||
return new RegistryChangeSet() { Changes = changes };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.Diagnostics;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ShortcutGuideModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Shortcut Guide";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ShortcutGuide;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredShortcutGuideEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.ShortcutGuide.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ShortcutGuide";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SupressLaunchOnModuleEnabled;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<ShortcutGuideSettings>(Name).Properties.OpenShortcutGuide, () =>
|
||||
{
|
||||
if (Process.GetProcessesByName(ProcessName).Length == 0)
|
||||
{
|
||||
LaunchProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessExit();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class WorkspacesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Workspaces";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Workspaces;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredWorkspacesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.WorkspacesEditor.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.WorkspacesEditor";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<WorkspacesSettings>(Name).Properties.Hotkey, () =>
|
||||
{
|
||||
LaunchProcess();
|
||||
}));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
}
|
||||
}
|
||||
@@ -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.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ZoomItModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "ZoomIt";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ZoomIt;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredZoomItEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.ZoomIt.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ZoomIt";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, Action> CustomActions { get => new() { { "refresh_settings", () => OnSettingsChanged() } }; }
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
using var refreshSettingsEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ZoomItRefreshSettingsEvent());
|
||||
refreshSettingsEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
346
src/RunnerV2/RunnerV2/NativeMethods.cs
Normal file
346
src/RunnerV2/RunnerV2/NativeMethods.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
// 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.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace RunnerV2
|
||||
{
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
[LibraryImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
|
||||
|
||||
[LibraryImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, ref TokenElevation tokenInformation, uint tokenInformationLength, out uint returnLength);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool CloseHandle(IntPtr hObject);
|
||||
|
||||
internal enum TOKEN_INFORMATION_CLASS
|
||||
{
|
||||
TOKEN_ELEVATION = 20,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct TokenElevation
|
||||
{
|
||||
public uint TokenIsElevated;
|
||||
}
|
||||
|
||||
internal const int TOKENQUERY = 0x0008;
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool AppendMenuW(IntPtr hMenu, uint uFlags, UIntPtr uIDNewItem, string lpNewItem);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial IntPtr CreatePopupMenu();
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr FindWindowW(string lpClassName, string lpWindowName);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
|
||||
|
||||
internal const uint NIMADD = 0x00000000;
|
||||
internal const uint NIMDELETE = 0x00000002;
|
||||
|
||||
internal struct NOTIFYICONDATA
|
||||
{
|
||||
public uint CbSize;
|
||||
public IntPtr HWnd;
|
||||
public uint UId;
|
||||
public uint UFlags;
|
||||
public uint UCallbackMessage;
|
||||
public IntPtr HIcon;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string SzTip;
|
||||
public uint DwState;
|
||||
public uint DwStateMask;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string SzInfo;
|
||||
public uint UTimeoutOrVersion;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string SzInfoTitle;
|
||||
public uint DwInfoFlags;
|
||||
public Guid GuidItem;
|
||||
public IntPtr HBalloonIcon;
|
||||
}
|
||||
|
||||
[DllImport("shell32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool Shell_NotifyIcon(uint dwMessage, ref NOTIFYICONDATA lpdata);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, uint action, IntPtr pChangeFilterStruct);
|
||||
|
||||
internal const uint CSVREDRAW = 0x0001;
|
||||
internal const uint CSHREDRAW = 0x0002;
|
||||
|
||||
internal const uint WSOVERLAPPEDWINDOW = 0x00CF0000;
|
||||
internal const uint WSPOPUP = 0x80000000;
|
||||
|
||||
internal const int CWUSEDEFAULT = unchecked((int)0x80000000);
|
||||
|
||||
internal static readonly IntPtr IDCARROW = new(32512);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern IntPtr GetMessageW(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool TranslateMessage(ref MSG lpMsg);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DispatchMessageW(ref MSG lpMsg);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool PostMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
internal static partial ushort AddAtomW([MarshalAs(UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
internal struct MSG
|
||||
{
|
||||
public IntPtr HWnd;
|
||||
public uint Message;
|
||||
public UIntPtr WParam;
|
||||
public long LParam;
|
||||
public ulong Time;
|
||||
public Point Pt;
|
||||
}
|
||||
|
||||
internal enum WindowMessages : uint
|
||||
{
|
||||
COMMAND = 0x0111,
|
||||
HOTKEY = 0x0312,
|
||||
ICON_NOTIFY = 0x0800,
|
||||
WINDOWPOSCHANGING = 0x0046,
|
||||
DESTROY = 0x0002,
|
||||
REFRESH_SETTINGS = 0x0400 + 2,
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern ushort RegisterClassW(ref WNDCLASS lpWndClass);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = false)]
|
||||
internal static partial IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial uint RegisterWindowMessageW([MarshalAs(UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial nint CreateWindowExW(
|
||||
uint dwExStyle,
|
||||
string lpClassName,
|
||||
string lpWindowName,
|
||||
uint dwStyle,
|
||||
int x,
|
||||
int y,
|
||||
int nWidth,
|
||||
int nHeight,
|
||||
IntPtr hWndParent,
|
||||
IntPtr hMenu,
|
||||
IntPtr hInstance,
|
||||
IntPtr lpParam);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct WNDCLASS
|
||||
{
|
||||
public uint Style;
|
||||
public WndProc LpfnWndProc;
|
||||
public int CbClsExtra;
|
||||
public int CbWndExtra;
|
||||
public IntPtr HInstance;
|
||||
public IntPtr HIcon;
|
||||
public IntPtr HCursor;
|
||||
public IntPtr HbrBackground;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string LpszMenuName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string LpszClassName;
|
||||
}
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string StringSecurityDescriptor,
|
||||
uint StringSDRevision,
|
||||
out IntPtr SecurityDescriptor,
|
||||
out uint SecurityDescriptorSize);
|
||||
|
||||
[DllImport("Advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool MakeAbsoluteSD(
|
||||
IntPtr pSelfRelativeSD,
|
||||
IntPtr pAbsoluteSD,
|
||||
ref uint lpdwAbsoluteSDSize,
|
||||
IntPtr pDacl,
|
||||
ref uint lpdwDaclSize,
|
||||
IntPtr pSacl,
|
||||
ref uint lpdwSaclSize,
|
||||
IntPtr pOwner,
|
||||
ref uint lpdwOwnerSize,
|
||||
IntPtr pPrimaryGroup,
|
||||
ref uint lpdwPrimaryGroupSize);
|
||||
|
||||
[DllImport("ole32.dll", SetLastError = true)]
|
||||
internal static extern int CoInitializeSecurity(
|
||||
IntPtr pSecDesc,
|
||||
int cAuthSvc,
|
||||
IntPtr asAuthSvc,
|
||||
IntPtr pReserved1,
|
||||
uint dwAuthnLevel,
|
||||
uint dwImpLevel,
|
||||
IntPtr pAuthList,
|
||||
uint dwCapabilities,
|
||||
IntPtr pReserved3);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize);
|
||||
|
||||
[LibraryImport("Shell32.dll", SetLastError = true)]
|
||||
internal static partial void SHChangeNotify(
|
||||
uint wEventId,
|
||||
uint uFlags,
|
||||
IntPtr dwItem1,
|
||||
IntPtr dwItem2);
|
||||
|
||||
internal const uint SHCNE_ASSOCCHANGED = 0x8000000;
|
||||
internal const uint SHCNF_IDLIST = 0x0;
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr OpenSCManagerW(string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr OpenServiceW(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool ControlService(IntPtr hService, uint dwControl, ref ServiceStatus lpServiceStatus);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool CloseServiceHandle(IntPtr hSCObject);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool StartServiceW(IntPtr hService, uint dwNumServiceArgs, IntPtr lpServiceArgVectors);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool QueryServiceStatusW(IntPtr hService, ref ServiceStatus lpServiceStatus);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool DeleteService(IntPtr hService);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool QueryServiceConfigW(IntPtr hService, IntPtr lpServiceConfig, uint cbBufSize, out uint pcbBytesNeeded);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ChangeServiceConfigW(
|
||||
IntPtr hService,
|
||||
uint dwServiceType,
|
||||
uint dwStartType,
|
||||
uint dwErrorControl,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup,
|
||||
IntPtr lpdwTagId,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDependencies,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpPassword,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool SetServiceObjectSecurity(
|
||||
IntPtr hService,
|
||||
uint dwSecurityInformation,
|
||||
IntPtr pSecurityDescriptor);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
internal static extern IntPtr CreateServiceW(
|
||||
IntPtr hSCManager,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName,
|
||||
uint dwDesiredAccess,
|
||||
uint dwServiceType,
|
||||
uint dwStartType,
|
||||
uint dwErrorControl,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup,
|
||||
IntPtr lpdwTagId,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDependencies,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpPassword);
|
||||
|
||||
internal const uint SCMANAGERALLACCESS = 0x000F0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020;
|
||||
|
||||
internal const uint SERVICEALLACCESS = 0x000F0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ServiceStatus
|
||||
{
|
||||
public uint dwServiceType;
|
||||
public uint dwCurrentState;
|
||||
public uint dwControlsAccepted;
|
||||
public uint dwWin32ExitCode;
|
||||
public uint dwServiceSpecificExitCode;
|
||||
public uint dwCheckPoint;
|
||||
public uint dwWaitHint;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct QueryServiceConfig
|
||||
{
|
||||
public uint dwServiceType;
|
||||
public uint dwStartType;
|
||||
public uint dwErrorControl;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpBinaryPathName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpLoadOrderGroup;
|
||||
public uint dwTagId;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpDependencies;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpServiceStartName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpDisplayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
173
src/RunnerV2/RunnerV2/Program.cs
Normal file
173
src/RunnerV2/RunnerV2/Program.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
// 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.Linq;
|
||||
using System.Reflection;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.Win32;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
using Settings.UI.Library;
|
||||
|
||||
internal sealed class Program
|
||||
{
|
||||
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
|
||||
|
||||
internal static GeneralSettings GeneralSettings => _settingsUtils.GetSettings<GeneralSettings>();
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
string securityDescriptor =
|
||||
"O:BA" // Owner: Builtin (local) administrator
|
||||
+ "G:BA" // Group: Builtin (local) administrator
|
||||
+ "D:"
|
||||
+ "(A;;0x7;;;PS)" // Access allowed on COM_RIGHTS_EXECUTE, _LOCAL, & _REMOTE for Personal self
|
||||
+ "(A;;0x7;;;IU)" // Access allowed on COM_RIGHTS_EXECUTE for Interactive Users
|
||||
+ "(A;;0x3;;;SY)" // Access allowed on COM_RIGHTS_EXECUTE, & _LOCAL for Local system
|
||||
+ "(A;;0x7;;;BA)" // Access allowed on COM_RIGHTS_EXECUTE, _LOCAL, & _REMOTE for Builtin (local) administrator
|
||||
+ "(A;;0x3;;;S-1-15-3-1310292540-1029022339-4008023048-2190398717-53961996-4257829345-603366646)" // Access allowed on COM_RIGHTS_EXECUTE, & _LOCAL for Win32WebViewHost package capability
|
||||
+ "S:"
|
||||
+ "(ML;;NX;;;LW)"; // Integrity label on No execute up for Low mandatory level
|
||||
|
||||
COMUtils.InitializeCOMSecurity(securityDescriptor);
|
||||
|
||||
switch (ShouldRunInSpecialMode(args))
|
||||
{
|
||||
case SpecialMode.None:
|
||||
break;
|
||||
case SpecialMode.UpdateNow:
|
||||
UpdateNow();
|
||||
return;
|
||||
case SpecialMode.DisableCantDragElevatedNotification:
|
||||
Environment.Exit(NotificationHelper.DisableToast(NotificationHelper.ToastType.ElevatedDontShowAgain) ? 1 : 0);
|
||||
return;
|
||||
case SpecialMode.CouldntToggleFileExplorerModulesNotification:
|
||||
Environment.Exit(NotificationHelper.DisableToast(NotificationHelper.ToastType.CouldntToggleFileExplorerModules) ? 1 : 0);
|
||||
return;
|
||||
default:
|
||||
throw new NotImplementedException("Special modes are not implemented yet.");
|
||||
}
|
||||
|
||||
bool shouldOpenSettings = args.Any(s => s.StartsWith("--open-settings", StringComparison.InvariantCulture));
|
||||
bool shouldOpenSettingsToSpecificPage = args.Any(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture));
|
||||
|
||||
// Check if PowerToys is already running
|
||||
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
|
||||
{
|
||||
IntPtr hwndMain = NativeMethods.FindWindowW(Runner.TrayWindowClassName, null!);
|
||||
NativeMethods.PostMessageW(hwndMain, 0x0111, 1, IntPtr.Zero);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GPOWrapper.GetAllowDataDiagnosticsValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Registry.CurrentUser.OpenSubKey("Software\\Classes\\PowerToys", true)?.SetValue("AllowDataDiagnostics", 0, RegistryValueKind.DWord);
|
||||
}
|
||||
|
||||
bool isElevated = ElevationHelper.IsProcessElevated();
|
||||
bool hasDontElevateArgument = args.Contains("--dont-elevate");
|
||||
bool runElevatedSetting = GeneralSettings.RunElevated;
|
||||
bool hasRestartedElevatedArgment = args.Contains("--restartedElevated");
|
||||
|
||||
Action afterInitializationAction = () => { };
|
||||
Version version = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
|
||||
if ($"v{version.Major}.{version.Minor}.{version.Build}" != _settingsUtils.GetSettings<LastVersionRunSettings>(fileName: "last_version_run.json").LastVersion && (!GeneralSettings.ShowWhatsNewAfterUpdates || GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() != GpoRuleConfigured.Disabled))
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
Logger.LogInfo("Open SCOOBE window because the version differs from the last run version");
|
||||
SettingsHelper.OpenSettingsWindow(showScoobeWindow: true);
|
||||
};
|
||||
}
|
||||
|
||||
if (!_settingsUtils.GetSettings<OOBESettings>(fileName: "oobe_settings.json").OpenedAtFirstLaunch)
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
Logger.LogInfo("Open OOBE window because it is the first launch");
|
||||
SettingsHelper.OpenSettingsWindow(showOobeWindow: true);
|
||||
};
|
||||
}
|
||||
|
||||
if (shouldOpenSettings)
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
SettingsHelper.OpenSettingsWindow(additionalArguments: shouldOpenSettingsToSpecificPage ? args.First(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture)).Replace("--open-settings=", string.Empty, StringComparison.InvariantCulture) : null);
|
||||
};
|
||||
}
|
||||
|
||||
// Set last version run
|
||||
_settingsUtils.SaveSettings(new LastVersionRunSettings() { LastVersion = $"v{version.Major}.{version.Minor}.{version.Build}" }.ToJsonString(), fileName: "last_version_run.json");
|
||||
|
||||
switch ((isElevated, hasDontElevateArgument, runElevatedSetting, hasRestartedElevatedArgment))
|
||||
{
|
||||
case (true, true, false, _):
|
||||
// Todo: Scheudle restart as non elevated
|
||||
throw new NotImplementedException();
|
||||
case (true, _, _, _):
|
||||
case (_, _, false, _):
|
||||
case (_, true, _, _):
|
||||
case (false, _, _, true):
|
||||
GeneralSettings tempGeneralSettings = GeneralSettings;
|
||||
tempGeneralSettings.IsElevated = isElevated;
|
||||
_settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString());
|
||||
|
||||
Runner.Run(afterInitializationAction);
|
||||
break;
|
||||
default:
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated;
|
||||
break;
|
||||
}
|
||||
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the application should run in a special mode based on the provided arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments passed to <see cref="Main(string[])"/></param>
|
||||
/// <returns>The <see cref="SpecialMode"/> the app should run in.</returns>
|
||||
private static SpecialMode ShouldRunInSpecialMode(string[] args)
|
||||
{
|
||||
if (args.Length > 0 && args[0].StartsWith("powertoys://", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
Uri uri = new(args[0]);
|
||||
string host = uri.Host.ToLowerInvariant();
|
||||
return host switch
|
||||
{
|
||||
"update_now" => SpecialMode.UpdateNow,
|
||||
"cant_drag_elevated_disable" => SpecialMode.DisableCantDragElevatedNotification,
|
||||
"couldnt_toggle_powerpreview_modules_disable" => SpecialMode.CouldntToggleFileExplorerModulesNotification,
|
||||
_ => SpecialMode.None,
|
||||
};
|
||||
}
|
||||
|
||||
return SpecialMode.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the update process for PowerToys.
|
||||
/// </summary>
|
||||
private static void UpdateNow()
|
||||
{
|
||||
Logger.LogInfo("Starting update process for PowerToys.");
|
||||
|
||||
Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
FileName = "PowerToys.Update.exe",
|
||||
Arguments = "-update_now",
|
||||
});
|
||||
}
|
||||
}
|
||||
369
src/RunnerV2/RunnerV2/Runner.cs
Normal file
369
src/RunnerV2/RunnerV2/Runner.cs
Normal file
@@ -0,0 +1,369 @@
|
||||
// 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.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
using RunnerV2.ModuleInterfaces;
|
||||
using Update;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2
|
||||
{
|
||||
internal static partial class Runner
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the window handle for the Runner main window that hosts the tray icon and receives system messages.
|
||||
/// </summary>
|
||||
public static nint RunnerHwnd { get; private set; }
|
||||
|
||||
public const string TrayWindowClassName = "pt_tray_icon_window_class";
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the currently loaded modules.
|
||||
/// </summary>
|
||||
public static List<IPowerToysModule> LoadedModules { get; } = [];
|
||||
|
||||
private static List<IPowerToysModule> _failedModuleLoads = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all available PowerToys modules.
|
||||
/// </summary>
|
||||
public static FrozenSet<IPowerToysModule> ModulesToLoad { get; } =
|
||||
[
|
||||
new ColorPickerModuleInterface(),
|
||||
new AlwaysOnTopModuleInterface(),
|
||||
new HostsModuleInterface(),
|
||||
new PowerAccentModuleInterface(),
|
||||
new AdvancedPasteModuleInterface(),
|
||||
new AwakeModuleInterface(),
|
||||
new CmdNotFoundModuleInterface(),
|
||||
new CommandPaletteModuleInterface(),
|
||||
new CropAndLockModuleInterface(),
|
||||
new EnvironmentVariablesModuleInterface(),
|
||||
new RegistryPreviewModuleInterface(),
|
||||
new FileExplorerModuleInterface(),
|
||||
new ZoomItModuleInterface(),
|
||||
new PowerOCRModuleInterface(),
|
||||
new MeasureToolModuleInterface(),
|
||||
new MouseJumpModuleInterface(),
|
||||
new FancyZonesModuleInterface(),
|
||||
new PowerToysRunModuleInterface(),
|
||||
new KeyboardManagerModuleInterface(),
|
||||
new LightSwitchModuleInterface(),
|
||||
new CursorWrapModuleInterface(),
|
||||
new FindMyMouseModuleInterface(),
|
||||
new WorkspacesModuleInterface(),
|
||||
new MousePointerCrosshairsModuleInterface(),
|
||||
new MouseHighlighterModuleInterface(),
|
||||
new MouseWithoutBordersModuleInterface(),
|
||||
new NewPlusModuleInterface(),
|
||||
new PowerRenameModuleInterface(),
|
||||
new ImageResizerModuleInterface(),
|
||||
new FileLocksmithModuleInterface(),
|
||||
new ShortcutGuideModuleInterface(),
|
||||
new PeekModuleInterface(),
|
||||
new PowerDisplayModuleInterface(),
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Runs the main message loop for Runner.
|
||||
/// </summary>
|
||||
/// <param name="afterInitializationAction">A function to execute after initialization.</param>
|
||||
internal static void Run(Action afterInitializationAction)
|
||||
{
|
||||
Logger.LogInfo("Runner started");
|
||||
|
||||
InitializeTrayWindow();
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
QuickAccessHelper.Start();
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook("QuickAccess", SettingsUtils.Default.GetSettings<GeneralSettings>().QuickAccessShortcut, QuickAccessHelper.Show);
|
||||
}
|
||||
|
||||
Task.Run(UpdateUtilities.UninstallPreviousMsixVersions);
|
||||
|
||||
foreach (IPowerToysModule module in ModulesToLoad)
|
||||
{
|
||||
ToggleModuleStateBasedOnEnabledProperty(module);
|
||||
}
|
||||
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
CentralizedKeyboardHookManager.Start();
|
||||
|
||||
afterInitializationAction();
|
||||
|
||||
MessageLoop();
|
||||
}
|
||||
|
||||
private static readonly uint _taskbarCreatedMessage = RegisterWindowMessageW("TaskbarCreated");
|
||||
|
||||
/// <summary>
|
||||
/// The main message loop that processes Windows messages.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void MessageLoop()
|
||||
{
|
||||
while (GetMessageW(out MSG msg, IntPtr.Zero, 0, 0) != 0 || true)
|
||||
{
|
||||
TranslateMessage(ref msg);
|
||||
DispatchMessageW(ref msg);
|
||||
|
||||
// Supress duplicate handling of HOTKEY messages
|
||||
if (msg.Message == (uint)WindowMessages.HOTKEY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HandleMessage(msg.HWnd, msg.Message, (nint)msg.WParam, (nint)msg.LParam);
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes Runner and all loaded modules.
|
||||
/// </summary>
|
||||
[DoesNotReturn]
|
||||
internal static void Close()
|
||||
{
|
||||
TrayIconManager.StopTrayIcon();
|
||||
SettingsHelper.CloseSettingsWindow();
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
QuickAccessHelper.Stop();
|
||||
|
||||
foreach (IPowerToysModule module in LoadedModules)
|
||||
{
|
||||
try
|
||||
{
|
||||
module.Disable();
|
||||
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.ProcessExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the state of a module based on its enabled property and GPO rules.
|
||||
/// </summary>
|
||||
/// <param name="module">The module to toggle</param>
|
||||
public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + module.Name + "\\ModuleInterface\\Logs");
|
||||
if (_failedModuleLoads.Contains(module))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ((module.Enabled && (module.GpoRuleConfigured != PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)) || module.GpoRuleConfigured == PowerToys.GPOWrapper.GpoRuleConfigured.Enabled)
|
||||
{
|
||||
/* Todo: conflict manager */
|
||||
|
||||
if (!LoadedModules.Contains(module))
|
||||
{
|
||||
module.Enable();
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.LaunchProcess(true);
|
||||
}
|
||||
|
||||
LoadedModules.Add(module);
|
||||
}
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule(module.Name);
|
||||
|
||||
if (module is IPowerToysModuleShortcutsProvider shortcutsProvider)
|
||||
{
|
||||
foreach (var shortcut in shortcutsProvider.Shortcuts.ToArray())
|
||||
{
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook(module.Name, shortcut.Hotkey, shortcut.Action);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if RELEASE
|
||||
MessageBox.Show($"The module {module.Name} failed to load: \n" + e.Message, "Error: " + e.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
#endif
|
||||
Logger.LogError($"The module {module.Name} failed to load: \n", e);
|
||||
_failedModuleLoads.Add(module);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
module.Disable();
|
||||
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.ProcessExit();
|
||||
}
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule(module.Name);
|
||||
|
||||
LoadedModules.Remove(module);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if RELEASE
|
||||
MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error: " + e.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
#endif
|
||||
Logger.LogError($"The module {module.Name} failed to unload: \n", e);
|
||||
_failedModuleLoads.Add(module);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the tray window to receive system messages.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void InitializeTrayWindow()
|
||||
{
|
||||
IntPtr hInstance = Process.GetCurrentProcess().MainModule!.BaseAddress;
|
||||
IntPtr hCursor = Cursors.Arrow.Handle;
|
||||
IntPtr hIcon = SystemIcons.Application.Handle;
|
||||
|
||||
var wc = new WNDCLASS
|
||||
{
|
||||
HCursor = hCursor,
|
||||
HInstance = hInstance,
|
||||
LpszClassName = TrayWindowClassName,
|
||||
Style = CSHREDRAW | CSVREDRAW,
|
||||
LpfnWndProc = HandleMessage,
|
||||
HIcon = hIcon,
|
||||
HbrBackground = IntPtr.Zero,
|
||||
LpszMenuName = string.Empty,
|
||||
CbClsExtra = 0,
|
||||
CbWndExtra = 0,
|
||||
};
|
||||
|
||||
_ = RegisterClassW(ref wc);
|
||||
|
||||
RunnerHwnd = CreateWindowExW(
|
||||
0,
|
||||
wc.LpszClassName,
|
||||
TrayWindowClassName,
|
||||
WSOVERLAPPEDWINDOW | WSPOPUP,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
wc.HInstance,
|
||||
IntPtr.Zero);
|
||||
|
||||
if (RunnerHwnd == IntPtr.Zero)
|
||||
{
|
||||
var err = Marshal.GetLastPInvokeError();
|
||||
MessageBox.Show($"CreateWindowExW failed. LastError={err}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles Windows messages sent to the tray window.
|
||||
/// </summary>
|
||||
private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case (uint)WindowMessages.ICON_NOTIFY:
|
||||
TrayIconManager.ProcessTrayIconMessage(lParam);
|
||||
break;
|
||||
case (uint)WindowMessages.COMMAND:
|
||||
TrayIconManager.ProcessTrayMenuCommand((nuint)wParam);
|
||||
break;
|
||||
case (uint)WindowMessages.WINDOWPOSCHANGING:
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
case (uint)WindowMessages.DESTROY:
|
||||
Close();
|
||||
break;
|
||||
case (uint)WindowMessages.REFRESH_SETTINGS:
|
||||
foreach (IPowerToysModule module in ModulesToLoad)
|
||||
{
|
||||
ToggleModuleStateBasedOnEnabledProperty(module);
|
||||
}
|
||||
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule("QuickAccess");
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook("QuickAccess", SettingsUtils.Default.GetSettings<GeneralSettings>().QuickAccessShortcut, QuickAccessHelper.Show);
|
||||
}
|
||||
else
|
||||
{
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule("QuickAccess");
|
||||
QuickAccessHelper.Stop();
|
||||
}
|
||||
|
||||
TrayIconManager.UpdateTrayIcon();
|
||||
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
else
|
||||
{
|
||||
TrayIconManager.StopTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if (msg == _taskbarCreatedMessage && SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/RunnerV2/RunnerV2/RunnerV2.csproj
Normal file
33
src/RunnerV2/RunnerV2/RunnerV2.csproj
Normal file
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\Common.SelfContained.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Description>PowerToys Runner</Description>
|
||||
<AssemblyName>PowerToys</AssemblyName>
|
||||
<OutputPath>..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\GPOWrapperProjection\GPOWrapperProjection.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedCsWin32\ManagedCsWin32.csproj" />
|
||||
<ProjectReference Include="..\..\modules\poweraccent\PowerAccent.UI\PowerAccent.UI.csproj" />
|
||||
<ProjectReference Include="..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\..\Update\Update.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\PowerToysDark.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\PowerToysLight.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
18
src/RunnerV2/RunnerV2/app.manifest
Normal file
18
src/RunnerV2/RunnerV2/app.manifest
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
BIN
src/RunnerV2/RunnerV2/icon.ico
Normal file
BIN
src/RunnerV2/RunnerV2/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
@@ -1,234 +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/updating/updating.h>
|
||||
#include <common/updating/updateState.h>
|
||||
#include <common/updating/installer.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/HttpClient.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 <Msi.h>
|
||||
|
||||
#include "../runner/tray_icon.h"
|
||||
#include "../runner/UpdateUtils.h"
|
||||
|
||||
using namespace cmdArg;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::optional<fs::path> CopySelfToTempDir()
|
||||
{
|
||||
std::error_code error;
|
||||
auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe";
|
||||
fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error);
|
||||
if (error)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::move(dst_path);
|
||||
}
|
||||
|
||||
std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
{
|
||||
using namespace updating;
|
||||
|
||||
isUpToDate = false;
|
||||
|
||||
auto state = UpdateState::read();
|
||||
|
||||
const auto new_version_info = get_github_version_info_async().get();
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = download_new_version(std::get<new_version_download_info>(*new_version_info)).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
else if (state.state == UpdateState::readyToInstall)
|
||||
{
|
||||
fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename };
|
||||
if (fs::is_regular_file(installer))
|
||||
{
|
||||
return std::move(installer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"Couldn't find a downloaded installer {}", installer.native());
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else if (state.state == UpdateState::upToDate)
|
||||
{
|
||||
isUpToDate = true;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Logger::error("Invoked with -update_now argument, but update state was invalid");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool InstallNewVersionStage1(fs::path installer)
|
||||
{
|
||||
if (auto copy_in_temp = CopySelfToTempDir())
|
||||
{
|
||||
// Detect if PT was running
|
||||
const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr);
|
||||
|
||||
if (pt_main_window != nullptr)
|
||||
{
|
||||
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
|
||||
arguments += L" \"";
|
||||
arguments += installer.c_str();
|
||||
arguments += L"\"";
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = copy_in_temp->c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
|
||||
sei.lpParameters = arguments.c_str();
|
||||
return ShellExecuteExW(&sei) == TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool InstallNewVersionStage2(std::wstring installer_path)
|
||||
{
|
||||
std::transform(begin(installer_path), end(installer_path), begin(installer_path), ::towlower);
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (installer_path.ends_with(L".msi"))
|
||||
{
|
||||
success = MsiInstallProductW(installer_path.data(), nullptr) == ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's not .msi, then it's a wix bootstrapper
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE };
|
||||
sei.lpFile = installer_path.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
std::wstring parameters = L"/passive /norestart";
|
||||
sei.lpParameters = parameters.c_str();
|
||||
|
||||
success = ShellExecuteExW(&sei) == TRUE;
|
||||
|
||||
// Wait for the install completion
|
||||
if (success)
|
||||
{
|
||||
WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(sei.hProcess, &exitCode);
|
||||
success = exitCode == 0;
|
||||
CloseHandle(sei.hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = UpdateState::upToDate;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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::updateLogPath);
|
||||
Logger::init(LogSettings::updateLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
|
||||
if (action == UPDATE_NOW_LAUNCH_STAGE1)
|
||||
{
|
||||
bool isUpToDate = false;
|
||||
auto installerPath = ObtainInstaller(isUpToDate);
|
||||
bool failed = !installerPath.has_value();
|
||||
failed = failed || !InstallNewVersionStage1(std::move(*installerPath));
|
||||
if (failed)
|
||||
{
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = isUpToDate ? UpdateState::upToDate : UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
const bool failed = !InstallNewVersionStage2(args[2]);
|
||||
if (failed)
|
||||
{
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h PowerToys.Update.base.rc PowerToys.Update.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}</ProjectGuid>
|
||||
<RootNamespace>Update</RootNamespace>
|
||||
<ProjectName>PowerToys.Update</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\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="PowerToys.Update.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\notifications\notifications.vcxproj">
|
||||
<Project>{1d5be09d-78c0-4fd7-af00-ae7c1af7c525}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\updating\updating.vcxproj">
|
||||
<Project>{17da04df-e393-4397-9cf0-84dabe11032e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PowerToys.Update.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\PowerToys.Update.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</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('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
183
src/Update/Program.cs
Normal file
183
src/Update/Program.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading.Tasks;
|
||||
using Update;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
internal sealed partial class Program
|
||||
{
|
||||
private static readonly string _installerPath = Path.Combine(Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Microsoft",
|
||||
"PowerToys",
|
||||
"Updates"));
|
||||
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
string action = args[0];
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case UpdateStage.UPDATENOWLAUNCHSTAGE1:
|
||||
await PerformUpdateNowStage1();
|
||||
break;
|
||||
case UpdateStage.UPDATENOWLAUNCHSTAGE2:
|
||||
if (args.Length < 2)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
await PerformUpdateNowStage2(args[1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task PerformUpdateNowStage2(string installerPath)
|
||||
{
|
||||
Process installerProcess = new()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = installerPath,
|
||||
Arguments = "/passive /norestart",
|
||||
UseShellExecute = true,
|
||||
},
|
||||
};
|
||||
|
||||
installerProcess.Start();
|
||||
await installerProcess.WaitForExitAsync();
|
||||
|
||||
if (installerProcess.ExitCode == 0)
|
||||
{
|
||||
UpdateSettingsHelper.ProcessNoUpdateAvailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSettingsHelper.SetUpdateState(UpdatingSettings.UpdatingState.ErrorDownloading);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task PerformUpdateNowStage1()
|
||||
{
|
||||
UpdateSettingsHelper.TriggerUpdateCheck();
|
||||
UpdateSettingsHelper.UpdateInfo updateInfo = await UpdateSettingsHelper.GetUpdateAvailableInfo();
|
||||
|
||||
if (updateInfo is not UpdateSettingsHelper.UpdateInfo.UpdateAvailable ua)
|
||||
{
|
||||
// No update found
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy itsself to the temp folder
|
||||
File.Copy("PowerToys.Update.exe", Path.Combine(Path.GetTempPath(), "PowerToys.Update.exe"), true);
|
||||
|
||||
string? installerFilePath = null;
|
||||
|
||||
switch (UpdateSettingsHelper.GetUpdateState())
|
||||
{
|
||||
case UpdatingSettings.UpdatingState.ReadyToDownload:
|
||||
case UpdatingSettings.UpdatingState.ErrorDownloading:
|
||||
CleanupUpdates();
|
||||
installerFilePath = await DownloadFile(ua.InstallerDownloadUrl.ToString(), ua.InstallerFilename);
|
||||
break;
|
||||
case UpdatingSettings.UpdatingState.ReadyToInstall:
|
||||
installerFilePath = Path.Combine(_installerPath, ua.InstallerFilename);
|
||||
if (!File.Exists(installerFilePath))
|
||||
{
|
||||
// Installer not found
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case UpdatingSettings.UpdatingState.UpToDate:
|
||||
Environment.Exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (installerFilePath == null)
|
||||
{
|
||||
UpdateSettingsHelper.SetUpdateState(UpdatingSettings.UpdatingState.ErrorDownloading);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr runnerHwnd = FindWindowW("pt_tray_icon_window_class");
|
||||
|
||||
if (runnerHwnd != IntPtr.Zero)
|
||||
{
|
||||
SendMessageW(runnerHwnd, 0x0010, IntPtr.Zero, IntPtr.Zero); // Send WM_CLOSE
|
||||
}
|
||||
|
||||
string arguments = $"{UpdateStage.UPDATENOWLAUNCHSTAGE2} \"{installerFilePath}\"";
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(Path.GetTempPath(), "PowerToys.Update.exe"),
|
||||
Arguments = arguments,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = Environment.CurrentDirectory,
|
||||
});
|
||||
}
|
||||
|
||||
private static async Task<string?> DownloadFile(string downloadUri, string downloadFileName)
|
||||
{
|
||||
HttpClient httpClient = new();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("PowerToys Runner"); // GitHub API requires a user-agent
|
||||
|
||||
// 3 Attempts to download the file
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
using FileStream fileStream = new(Path.Combine(_installerPath, downloadFileName), FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
await (await httpClient.GetStreamAsync(downloadUri)).CopyToAsync(fileStream);
|
||||
return fileStream.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void CleanupUpdates()
|
||||
{
|
||||
if (!Path.Exists(_installerPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string file in Directory.GetFiles(_installerPath).Where(f => f.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
private static partial IntPtr FindWindowW(string lpClassName);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
@@ -1,82 +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" xml:space="preserve">
|
||||
<value>An update to PowerToys is available.</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_UPDATE_NOW" xml:space="preserve">
|
||||
<value>Update now</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>
|
||||
<data name="GITHUB_NEW_VERSION_MORE_INFO" xml:space="preserve">
|
||||
<value>More info...</value>
|
||||
</data>
|
||||
<data name="TOAST_TITLE" xml:space="preserve">
|
||||
<value>PowerToys Update</value>
|
||||
</data>
|
||||
</root>
|
||||
22
src/Update/Update.csproj
Normal file
22
src/Update/Update.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\Common.SelfContained.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Description>PowerToys Runner</Description>
|
||||
<AssemblyName>PowerToys.Update</AssemblyName>
|
||||
<OutputPath>..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<_IsPublishing Condition="'$(_IsPublishing)'==''">false</_IsPublishing>
|
||||
</PropertyGroup>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(_IsPublishing)'!='true'">
|
||||
<Exec Command="dotnet publish "$(ProjectPath)" -c $(Configuration) -r $(RuntimeIdentifier) --self-contained -o "$(OutputPath)"" />
|
||||
</Target>
|
||||
</Project>
|
||||
227
src/Update/UpdateSettingsHelper.cs
Normal file
227
src/Update/UpdateSettingsHelper.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public static class UpdateSettingsHelper
|
||||
{
|
||||
private static Thread? _updateThread;
|
||||
|
||||
private const string INSTALLERFILENAME = "powertoyssetup";
|
||||
private const string USERINSTALLERFILENAME = "powertoysusersetup";
|
||||
|
||||
public static void TriggerUpdateCheck()
|
||||
{
|
||||
if (_updateThread is not null && _updateThread.IsAlive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_updateThread = new Thread(async () =>
|
||||
{
|
||||
UpdateInfo updateInfo = await GetUpdateAvailableInfo();
|
||||
switch (updateInfo)
|
||||
{
|
||||
case UpdateInfo.UpdateCheckFailed ucf:
|
||||
ProcessUpdateCheckFailed(ucf);
|
||||
break;
|
||||
case UpdateInfo.UpdateAvailable ua:
|
||||
ProcessUpdateAvailable(ua);
|
||||
break;
|
||||
case UpdateInfo.NoUpdateAvailable:
|
||||
ProcessNoUpdateAvailable();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
_updateThread.Start();
|
||||
}
|
||||
|
||||
internal record UpdateInfo
|
||||
{
|
||||
private UpdateInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public sealed record NoUpdateAvailable : UpdateInfo;
|
||||
|
||||
public sealed record UpdateAvailable(Uri ReleasePageUri, Version AvailableVersion, Uri InstallerDownloadUrl, string InstallerFilename) : UpdateInfo;
|
||||
|
||||
public sealed record UpdateCheckFailed(Exception Exception) : UpdateInfo;
|
||||
}
|
||||
|
||||
internal static async Task<UpdateInfo> GetUpdateAvailableInfo()
|
||||
{
|
||||
Version? currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
if (currentVersion is null)
|
||||
{
|
||||
// Todo: Log
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
|
||||
if (currentVersion is { Major: 0, Minor: 0 })
|
||||
{
|
||||
// Pre-release or local build, skip update check
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HttpClient httpClient = new();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("PowerToys Runner"); // GitHub API requires a user-agent
|
||||
Stream body = await httpClient.GetStreamAsync("https://api.github.com/repos/microsoft/PowerToys/releases/latest").ConfigureAwait(false);
|
||||
JsonElement releaseObject = (await JsonDocument.ParseAsync(body)).RootElement;
|
||||
Version latestVersion = new(releaseObject.GetProperty("tag_name").GetString()?.TrimStart('V', 'v') ?? throw new FormatException("The \"tag_name\" field could not be found"));
|
||||
string architectureString = RuntimeInformation.OSArchitecture switch
|
||||
{
|
||||
Architecture.X64 => "x64",
|
||||
Architecture.Arm64 => "arm64",
|
||||
_ => throw new InvalidDataException("Unknown architecture"),
|
||||
};
|
||||
|
||||
if (latestVersion > currentVersion)
|
||||
{
|
||||
Uri releasePageUri = new(releaseObject.GetProperty("html_url").GetString() ?? throw new FormatException("The \"html_url\" field could not be found"));
|
||||
|
||||
string requiredFilename = GetInstallScope() == InstallScope.PerMachine ? INSTALLERFILENAME : USERINSTALLERFILENAME;
|
||||
|
||||
Uri? installerDownloadUrl = null;
|
||||
string? installerFilename = null;
|
||||
|
||||
foreach (JsonElement asset in releaseObject.GetProperty("assets").EnumerateArray())
|
||||
{
|
||||
string? name = asset.GetProperty("name").GetString();
|
||||
string? browserDownloadUrl = asset.GetProperty("browser_download_url").GetString();
|
||||
|
||||
if (name is null
|
||||
|| browserDownloadUrl is null
|
||||
|| !name.Contains(requiredFilename, StringComparison.InvariantCultureIgnoreCase)
|
||||
|| !name.Contains(".exe", StringComparison.InvariantCultureIgnoreCase)
|
||||
|| !name.Contains(architectureString, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
installerDownloadUrl = new Uri(browserDownloadUrl);
|
||||
installerFilename = name;
|
||||
break;
|
||||
}
|
||||
|
||||
return installerDownloadUrl is null || installerFilename is null
|
||||
? new UpdateInfo.UpdateCheckFailed(new InvalidDataException("No installer found in GitHub release"))
|
||||
: new UpdateInfo.UpdateAvailable(releasePageUri, latestVersion, installerDownloadUrl, installerFilename);
|
||||
}
|
||||
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new UpdateInfo.UpdateCheckFailed(e);
|
||||
}
|
||||
}
|
||||
|
||||
private enum InstallScope
|
||||
{
|
||||
PerMachine,
|
||||
PerUser,
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static InstallScope GetInstallScope()
|
||||
{
|
||||
if (Registry.LocalMachine.OpenSubKey(@"Software\Classes\powertoys\", false) is not RegistryKey machineKey)
|
||||
{
|
||||
if (Registry.CurrentUser.OpenSubKey(@"Software\Classes\powertoys\", false) is not RegistryKey userKey)
|
||||
{
|
||||
// Both keys are missing
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
if (userKey.GetValue("InstallScope") is not string installScope)
|
||||
{
|
||||
userKey.Close();
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
userKey.Close();
|
||||
|
||||
return installScope.Contains("perUser") ? InstallScope.PerUser : InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
machineKey.Close();
|
||||
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
private static readonly string _settingsPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Microsoft",
|
||||
"PowerToys");
|
||||
|
||||
private static readonly string _updatingSettingsFile = Path.Combine(_settingsPath, "UpdateState.json");
|
||||
|
||||
private static void ProcessUpdateAvailable(UpdateInfo.UpdateAvailable updateAvailable)
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
Console.WriteLine($"Update available: {updateAvailable.AvailableVersion}");
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.ReadyToDownload;
|
||||
updatingSettings.ReleasePageLink = updateAvailable.ReleasePageUri.ToString();
|
||||
updatingSettings.DownloadedInstallerFilename = updateAvailable.InstallerFilename;
|
||||
updatingSettings.ReleasePageLink = updateAvailable.ReleasePageUri.ToString();
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static void ProcessNoUpdateAvailable()
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.UpToDate;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.DownloadedInstallerFilename = string.Empty;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
private static void ProcessUpdateCheckFailed(UpdateInfo.UpdateCheckFailed updateCheckFailed)
|
||||
{
|
||||
// Todo: Log failed attempt
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.NetworkError;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.DownloadedInstallerFilename = string.Empty;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static void SetUpdateState(UpdatingSettings.UpdatingState state)
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = state;
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static UpdatingSettings.UpdatingState GetUpdateState() => UpdatingSettings.LoadSettings().State;
|
||||
}
|
||||
}
|
||||
16
src/Update/UpdateStage.cs
Normal file
16
src/Update/UpdateStage.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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
internal static class UpdateStage
|
||||
{
|
||||
internal const string UPDATENOWLAUNCHSTAGE1 = "-update_now";
|
||||
internal const string UPDATENOWLAUNCHSTAGE2 = "-update_now_stage_2";
|
||||
}
|
||||
}
|
||||
44
src/Update/UpdateUtilities.cs
Normal file
44
src/Update/UpdateUtilities.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public static class UpdateUtilities
|
||||
{
|
||||
public static async void UninstallPreviousMsixVersions()
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Management.Deployment.PackageManager packageManager = new();
|
||||
var packages = packageManager.FindPackagesForUser(string.Empty, "Microsoft.PowerToys", "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US");
|
||||
|
||||
Version? currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
if (currentVersion == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var package in packages)
|
||||
{
|
||||
Version msixVersion = new(package.Id.Version.Major, package.Id.Version.Minor, package.Id.Version.Revision);
|
||||
if (msixVersion < currentVersion)
|
||||
{
|
||||
await packageManager.RemovePackageAsync(package.Id.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
src/Update/UpdatingSettings.cs
Normal file
124
src/Update/UpdatingSettings.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.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public sealed class UpdatingSettings
|
||||
{
|
||||
public enum UpdatingState
|
||||
{
|
||||
UpToDate = 0,
|
||||
ErrorDownloading,
|
||||
ReadyToDownload,
|
||||
ReadyToInstall,
|
||||
NetworkError,
|
||||
}
|
||||
|
||||
// Gets or sets a value of the updating state
|
||||
[JsonPropertyName("state")]
|
||||
public UpdatingState State { get; set; }
|
||||
|
||||
// Gets or sets a value of the release page url
|
||||
[JsonPropertyName("releasePageUrl")]
|
||||
public string ReleasePageLink { get; set; } = string.Empty;
|
||||
|
||||
// Gets or sets a value of the github last checked date
|
||||
[JsonPropertyName("githubUpdateLastCheckedDate")]
|
||||
public string LastCheckedDate { get; set; } = string.Empty;
|
||||
|
||||
// Gets or sets a value of the updating state
|
||||
[JsonPropertyName("downloadedInstallerFilename")]
|
||||
public string DownloadedInstallerFilename { get; set; } = string.Empty;
|
||||
|
||||
// Non-localizable strings: Files
|
||||
public const string SettingsFilePath = "\\Microsoft\\PowerToys\\";
|
||||
public const string SettingsFile = "UpdateState.json";
|
||||
|
||||
public string NewVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ReleasePageLink == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string version = ReleasePageLink.Substring(ReleasePageLink.LastIndexOf('/') + 1);
|
||||
return version.Trim();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string LastCheckedDateLocalized
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (LastCheckedDate == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
long seconds = long.Parse(LastCheckedDate, CultureInfo.CurrentCulture);
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(seconds).UtcDateTime;
|
||||
return date.ToLocalTime().ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatingSettings()
|
||||
{
|
||||
State = UpdatingState.UpToDate;
|
||||
}
|
||||
|
||||
public static UpdatingSettings LoadSettings()
|
||||
{
|
||||
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var file = localAppDataDir + SettingsFilePath + SettingsFile;
|
||||
|
||||
if (File.Exists(file))
|
||||
{
|
||||
try
|
||||
{
|
||||
FileStream inputStream = File.Open(file, FileMode.Open);
|
||||
StreamReader reader = new(inputStream);
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
reader.Dispose();
|
||||
|
||||
return JsonSerializer.Deserialize(data, UpdatingsSettingsSourceGenerationContext.Default.UpdatingSettings)!;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return new UpdatingSettings();
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this, UpdatingsSettingsSourceGenerationContext.Default.UpdatingSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/Update/UpdatingsSettingsSourceGenerationContext.cs
Normal file
22
src/Update/UpdatingsSettingsSourceGenerationContext.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(UpdatingSettings))]
|
||||
|
||||
internal sealed partial class UpdatingsSettingsSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user