diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index bfcdd94094..3c19d4949f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -10,7 +10,7 @@ body:
- type: input
attributes:
label: Microsoft PowerToys version
- placeholder: 0.63.0
+ placeholder: 0.68.0
description: Hover over system tray icon or look at Settings
validations:
required: true
@@ -60,9 +60,11 @@ body:
- Installer
- Keyboard Manager
- Mouse Utilities
+ - Paste as Plain Text
- PowerRename
- PowerToys Run
- Quick Accent
+ - Registry Preview
- Screen ruler
- Settings
- Shortcut Guide
diff --git a/.github/ISSUE_TEMPLATE/translation_issue.yml b/.github/ISSUE_TEMPLATE/translation_issue.yml
index 787f9ebb69..de38f7b61d 100644
--- a/.github/ISSUE_TEMPLATE/translation_issue.yml
+++ b/.github/ISSUE_TEMPLATE/translation_issue.yml
@@ -12,7 +12,7 @@ body:
- type: input
attributes:
label: Microsoft PowerToys version
- placeholder: 0.63.0
+ placeholder: 0.68.0
description: Hover over system tray icon or look at Settings
validations:
required: true
@@ -34,9 +34,11 @@ body:
- Installer
- Keyboard Manager
- Mouse Utilities
+ - Paste as Plain Text
- PowerRename
- PowerToys Run
- Quick Accent
+ - Registry Preview
- Screen ruler
- Settings
- Shortcut Guide
diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt
index 979f48ee4f..97520c020f 100644
--- a/.github/actions/spell-check/allow/names.txt
+++ b/.github/actions/spell-check/allow/names.txt
@@ -14,5 +14,6 @@ robmen
skycommand
snickler
sinclairinat
+TheJoeFin
Vidia
yifan
diff --git a/.github/actions/spell-check/excludes.txt b/.github/actions/spell-check/excludes.txt
index 1c42d9e4a9..3e04a7f21f 100644
--- a/.github/actions/spell-check/excludes.txt
+++ b/.github/actions/spell-check/excludes.txt
@@ -77,8 +77,10 @@
^\.gitmodules$
^\Q.github/workflows/spelling2.yml\E$
^\Q.pipelines/ESRPSigning_core.json\E$
-^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
+^\Qinstaller/PowerToysSetup/Settings.wxs\E$
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
+^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
+^\Qsrc/modules/MouseUtils/MouseJumpUI/MainForm.resx\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/CorruptJson/Microsoft/PowerToys/settings.json\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/v0.18.2/Microsoft/PowerToys/PowerRename/power-rename-ui-flags\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/v0.19.2/Microsoft/PowerToys/PowerRename/power-rename-ui-flags\E$
@@ -97,6 +99,7 @@
^src/modules/fancyzones/lib/FancyZonesWinHookEventIDs\.h$
^src/modules/imageresizer/dll/ContextMenuHandler\.rgs$
^src/modules/imageresizer/dll/ImageResizerExt\.rgs$
+^src/modules/MouseUtils/MouseJumpUI/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs$
^src/modules/powerrename/testapp/PowerRenameTest\.vcxproj\.filters$
^src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithHTMLImageTag\.txt$
^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag.txt$
diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index dadf68c544..11cc127869 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -1,15 +1,28 @@
aaaa
+AAAAEF
+AAB
+AABAD
+AACB
+AACD
+AAD
+AADF
+abap
Abbrivation
+ABE
abgr
abi
ABlocked
ABOUTBOX
Abug
+ACA
accctrl
Acceleratorkeys
ACCEPTFILES
ACCESSDENIED
accessibilityinsights
+ACDB
+ACFC
+ACFF
Acl
aclapi
AColumn
@@ -25,13 +38,22 @@ adml
admx
advapi
advfirewall
+AEAA
+AEAD
+AECC
+AED
+AEE
+AEEB
+AFAE
+AFAEFC
+AFDA
+AFE
AFeature
+AFFE
AFFINETRANSFORM
AFX
AGGREGATABLE
AHybrid
-Akrotiri
-Aktobe
ALarger
alekhyareddy
ALLAPPS
@@ -41,11 +63,10 @@ ALPHATYPE
Altdown
alwaysontop
amd
-AMF
AModifier
AMPROPERTY
AMPROPSETID
-Andreanof
+ANDSCANS
anges
angularsen
Animatable
@@ -53,6 +74,7 @@ ansicolor
ANull
AOC
aocfnapldcnfbofgmbbllojgocaelgdd
+AOT
APARTMENTTHREADED
APeriod
apidl
@@ -67,17 +89,15 @@ Applets
Applicationcan
applicationconfiguration
applicationframehost
-Applist
applog
appmanifest
+APPNAME
appref
apps
appwindow
appwiz
-appxpackage
APSTUDIO
AQS
-Aqtobe
ARCHITEW
arcosh
ARemapped
@@ -96,11 +116,9 @@ arw
asdf
AShortcut
ASingle
-Asn
ASSOCCHANGED
ASYNCWINDOWPLACEMENT
ASYNCWINDOWPOS
-Atikokan
atl
atlbase
atlcom
@@ -108,7 +126,6 @@ atleast
atlfile
atlstr
Attribs
-Atyrau
aumid
Aut
Authenticode
@@ -119,20 +136,41 @@ AUTOMATIONPROPERTIES
Autorun
AUTOUPDATE
AValid
-Avanc
awakeness
awakeversion
AYUV
+azcli
+azman
+azor
backtracer
+BAF
bak
-Bashkortostan
-Bayan
+BBE
bbwe
+BCA
+BCB
+BCCE
+BCCEA
bck
+BDB
+BDBAD
+BDCC
+BDDF
+BDFB
+BEAA
+BEB
+BEEAADF
+BEEC
+BEFA
Belarus
BESTEFFORT
betadele
betsegaw
+BFC
+BFDE
+BFEB
+BFF
+BFFA
BGR
bgra
bhid
@@ -147,8 +185,10 @@ BITMAPINFOHEADER
bitmask
BITSPIXEL
bla
+BLACKONWHITE
Blockquotes
blogs
+Blt
BLUEGRAY
Bluetooth
BLURBEHIND
@@ -167,10 +207,10 @@ bpmf
bpp
bricelam
BRIGHTGREEN
-Brotli
Browsable
bsd
bstr
+bthprops
bti
btn
BTNFACE
@@ -182,38 +222,63 @@ buildtask
buildtransitive
Burkina
Buryatia
+BUTTONUP
BVal
BValue
BYPOSITION
bytearray
-Caiguna
+CABD
CALG
callbackptr
+cameligo
calpwstr
Cangjie
CANRENAME
+CAPTUREBLT
CAPTURECHANGED
CARRAY
CAtl
+CBA
+CBB
+CBF
+CCCCDE
cch
+CCHDEVICENAME
+CCHFORMNAME
CCom
CContext
+CDAC
+CDBF
+CDCE
+CDD
+CDE
cdecl
CDeclaration
CDEF
cdpx
+CEAF
+CEBAC
+CEBD
+CECB
CElems
CENTERALIGN
+ceq
+certlm
+certmgr
+CFAADB
+CFBBF
+CFEE
+CFFEE
+CFFF
cguid
changecursor
Changemove
chdir
CHILDACTIVATE
CHILDWINDOW
-Choibalsan
chrdavis
Chrzan
-cht
+CHT
Chukotka
Chuuk
cidl
@@ -225,18 +290,16 @@ cla
clangformat
CLASSDC
CLASSNOTAVAILABLE
+clayton
clickable
clickonce
CLIENTEDGE
+clientid
clientside
CLIPCHILDREN
-Clipperton
CLIPSIBLINGS
+Cloneable
clrcall
-clrcompression
-clretwrc
-clrgc
-clrjit
Cls
CLSCTX
clsid
@@ -251,9 +314,8 @@ CMock
CMONITORS
cmpgt
cmyk
-Cng
+cne
cnt
-Cocklebiddy
coclass
CODENAME
codeofconduct
@@ -266,17 +328,19 @@ colorformat
colorhistory
colorhistorylimit
COLORKEY
+COLORONCOLOR
colorpicker
COLORREF
comctl
COMDAT
comdef
comdlg
+comexp
cominterop
commandline
COMMANDTITLE
commctrl
-Comoros
+compmgmt
COMPOSITIONFULL
comsupp
comsuppw
@@ -297,8 +361,6 @@ CONTROLL
CONTROLPARENT
Controlz
copiedcolorrepresentation
-coreclr
-corewebview
cortana
cotaskmem
COULDNOT
@@ -309,9 +371,11 @@ cppruntime
cppstd
cppwinrt
CProj
+createdump
CREATESCHEDULEDTASK
CREATESTRUCT
CREATEWINDOWFAILED
+CRECT
critsec
Crossdevice
CRSEL
@@ -324,13 +388,12 @@ CSRW
CStyle
CSY
CTest
-Ctl
CTRLALTDEL
Ctrls
Ctx
CUI
-Cunha
currentculture
+CURRENTDIR
CURSORINFO
cursorpos
customaction
@@ -342,14 +405,18 @@ cvtepu
cvtsi
cwd
cxfksword
+CXSCREEN
CXSMICON
CXVIRTUALSCREEN
cyberrex
+CYSCREEN
CYSMICON
CYVIRTUALSCREEN
cziplib
+DAA
Dac
dacl
+DAF
damienleroy
DANGEROUSLYCOMMITMERELYTODISKCACHE
Danmarkshavn
@@ -357,27 +424,36 @@ DARKPURPLE
DARKTEAL
DARKYELLOW
datareader
-datatemplate
Datavalue
+dataversion
DATAW
davidegiacometti
Dayof
+DBAE
+DBB
+DBBDA
+DBDE
Dbg
Dbghelp
-dbgshim
DBLCLKS
DBLEPSILON
+DCAB
DCapture
DCBA
+DCBC
+DCCB
+DCEFCB
+DCF
DCOM
dcommon
dcomp
dcompi
-DCompiler
DComposition
-dcr
-dcs
+DCR
+DCs
Dct
+DDCDD
+DDCE
DDEIf
DDevice
ddf
@@ -388,6 +464,7 @@ debian
debugbreak
DECLAR
declspec
+DED
Dedup
DEFAULTBOOTSTRAPPERINSTALLFOLDER
DEFAULTCOLOR
@@ -401,6 +478,8 @@ DEFPUSHBUTTON
deinitialization
DELA
DELAYCREATION
+DELETEDKEYIMAGE
+DELETESCANS
deletethis
Delimarsky
dend
@@ -409,23 +488,28 @@ Deondre
depersist
deprioritized
depsfileslistspath
-depsjsonpath
deref
DESKTOPABSOLUTEEDITING
DESKTOPABSOLUTEPARSING
desktopshorcutinstalled
desktopwindowxamlsource
-deu
+DEU
devblogs
devdocs
devenum
+devmgmt
+DEVMODEW
DEVMON
devpkey
DEVSOURCE
+DFAB
+DFB
+DFBEA
DIIRFLAG
dimm
directshow
DISABLEASACTIONKEY
+diskmgmt
DISPLAYCHANGE
DISPLAYCONFIG
displayname
@@ -440,7 +524,6 @@ dllmain
DNLEN
Dns
DONOTROUND
-DONTRESOLVEDLLREFERENCES
DONTVALIDATEPATH
dotnet
DPICHANGED
@@ -455,6 +538,8 @@ dreamsofameaningfullife
drf
drivedetectionwarning
dshow
+DSTINVERT
+DUMMYUNIONNAME
dutil
DVASPECT
DVASPECTINFO
@@ -487,13 +572,41 @@ dxgi
dxgidebug
dxgiformat
dxguid
+EAAFE
+EABF
+EAC
+EADC
+EAF
+EBCF
+EBD
+EBE
+ecl
ecount
EData
+EDB
+EDCCC
+EDFAE
Edid
+edis
EDITKEYBOARD
editkeyboardwindow
EDITSHORTCUTS
editshortcutswindow
+edshift
+EEA
+EEB
+EEBBE
+EEBD
+EED
+EEDA
+EEEE
+EEF
+EEFA
+EFB
+EFC
+EFDD
+EFE
+EFFEFC
EFile
eip
ekus
@@ -505,8 +618,7 @@ ENABLEDPOPUP
endpointvolume
endregion
ENTERSIZEMOVE
-enu
-enumerationoptions
+ENU
EOAC
epicgames
epu
@@ -514,19 +626,19 @@ ERASEBKGND
EREOF
EResize
ERole
+ERRORIMAGE
ERRORLEVEL
ERRORTITLE
ESettings
esize
-esn
esrp
-Eswatini
+estructuredtext
etl
etw
-Eucla
EUQ
eurochange
eventlog
+eventvwr
everytime
evt
EWXFORCE
@@ -539,6 +651,7 @@ Exa
exabyte
examplehandler
examplepowertoy
+EXAND
Excep
EXCEPINFO
EXCLUDEFROMCAPTURE
@@ -559,16 +672,47 @@ EXTENDEDVERBS
EXTRINSICPROPERTIES
EXTRINSICPROPERTIESONLY
eyetracker
+FABC
fabricbot
-fancyzones
+FAEDDA
+FAF
+FAFD
+fancymouse
+fancyzone
FANCYZONESDRAWLAYOUTTEST
FANCYZONESEDITOR
Farbraum
-Faroe
FARPROC
FASTPROPERTIESONLY
+FBB
+FBC
+FBDE
+FBF
+FCAE
+FCB
+FCCFF
+FCD
+FCDB
+FCDD
+FCE
+FDB
+FDBF
+FDC
+FDCD
+FDE
+FDEF
+FDF
fdw
+FECF
+FEDF
+FEEF
feimage
+FFB
+FFBCF
+FFBE
+FFDDD
+FFEB
+FFEBEF
fff
fileapi
FILEEXPLORER
@@ -602,9 +746,9 @@ frankychen
Froml
FROMTOUCH
FSCTL
+fsmgmt
FTYPE
Functiondiscoverykeys
-Futuna
fwlink
FZE
gabime
@@ -622,8 +766,6 @@ gcode
gdi
gdiplus
GDISCALED
-getancestor
-getasynckeystate
GETDESKWALLPAPER
GETDLGCODE
GETDPISCALEDSIZE
@@ -633,13 +775,15 @@ GETSTATE
GETTEXT
GETTEXTLENGTH
GHND
-globalassemblycache
-Globbing
GMEM
GNumber
google
+gpedit
gpo
+GPOCA
+GPT
gpu
+graphql
GSM
gtm
gui
@@ -677,11 +821,11 @@ hcwhite
hdc
HDR
hdrop
+hdwwiz
HEB
Heiko
Helpline
helptext
-Heure
HGFE
hglobal
hhk
@@ -717,13 +861,10 @@ HOMEPATH
homljgmgpmcbpjbnjpfijnhipfkiclkd
HOOKPROC
Hostbackdropbrush
-hostfxr
-hostpolicy
hotkeycontrol
hotkeys
hotlight
hotspot
-Hovd
HPAINTBUFFER
HPALETTE
HRAWINPUT
@@ -748,6 +889,7 @@ HVal
HValue
Hvci
hwb
+HWHEEL
HWINEVENTHOOK
hwnd
HWNDFIRST
@@ -772,7 +914,7 @@ IDecoder
IDesktop
IDirect
idl
-IDLIST
+idlist
IDOn
IDR
idx
@@ -801,7 +943,6 @@ IMAGERESIZEREXT
imageresizerinput
imageresizersettings
imagingdevices
-Imc
ime
IMetadata
imeutil
@@ -817,7 +958,6 @@ Inlines
inorder
INPC
inproc
-inputdev
INPUTHARDWARE
INPUTKEYBOARD
INPUTLANGCHANGED
@@ -832,6 +972,7 @@ INSTALLFOLDERTOPREVIOUSINSTALLFOLDER
INSTALLLOCATION
INSTALLMESSAGE
INSTALLPROPERTY
+installscopeperuser
INSTALLSTARTMENUSHORTCUT
INSTALLSTATE
Inste
@@ -839,7 +980,6 @@ Intelli
interactable
Interlop
INTRESOURCE
-Intrinsics
INVALIDARG
invalidoperatioexception
ipc
@@ -847,12 +987,12 @@ ipcmanager
IPlugin
IPower
IPREVIEW
-ipreviewhandler
ipreviewhandlervisualssetfont
IProperty
IPublic
IQuery
IReader
+irprops
isbi
ISearch
ISettings
@@ -864,11 +1004,10 @@ iss
ISurface
ITask
ith
-ithumbnail
+ITHUMBNAIL
Ittoqqortoormiit
IUI
IUnknown
-ivirtualdesktopmanager
IWbem
IWIC
iwr
@@ -880,12 +1019,13 @@ jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
jif
jjw
jobject
+joefinapps
jpe
-jpn
+JPN
jpnime
-JSONOf
Jsons
jsonval
+julia
junja
jxr
jyuwono
@@ -904,27 +1044,22 @@ keydown
keydropdowncontrol
keyevent
KEYEVENTF
+KEYIMAGE
keynum
keyremaps
Keytool
keyup
-Khakassia
-Khanty
-Khovd
+Kfiles
KILLFOCUS
-Kitts
+killrunner
Knownfolders
-Krai
+kotlin
KSPROPERTY
-Kwango
-Kwilu
Kybd
-Kyrgyzstan
-Kyzylorda
LAlt
Lambson
-LANGID
langword
+lastcodeanalysissucceeded
Lastdevice
Laute
laviusmotileng
@@ -941,13 +1076,16 @@ LCONTROL
LCtrl
Ldone
ldx
+LEFTDOWN
LEFTSCROLLBAR
+LEFTUP
lego
len
LError
Lessthan
LEVELID
LExit
+lexon
lhs
lhwnd
LIBID
@@ -966,7 +1104,6 @@ LMEM
LMENU
lnk
LOADFROMFILE
-LOADLIBRARYASDATAFILE
LOBYTE
LOCALAPPDATA
LOCALDISPLAY
@@ -980,7 +1117,6 @@ logconsole
logfile
LOGFONT
LOGFONTW
-LOGMSG
logon
LOGPIXELSX
LOn
@@ -994,14 +1130,18 @@ LPBYTE
LPCITEMIDLIST
LPCMINVOKECOMMANDINFO
LPCREATESTRUCT
+LPCRECT
LPCTSTR
LPCWSTR
lpdw
lpfn
+lpmi
LPINPUT
LPMINMAXINFO
+LPMONITORINFO
LPOSVERSIONINFOEXW
lprc
+LPPOINT
LPRECT
LPSAFEARRAY
LPSTR
@@ -1022,16 +1162,13 @@ lstrcmpi
lstrlen
LTRB
LTRREADING
-Luhansk
luid
+lusrmgr
LVal
LWA
lwin
LZero
lzw
-Maarten
-Macquarie
-Magadan
Mainwindow
majortype
MAJORVERSION
@@ -1039,10 +1176,7 @@ makecab
MAKEINTRESOURCE
MAKEINTRESOURCEW
makepri
-Mangere
-Mangystau
manifestdependency
-Mansi
MAPPEDTOSAMEKEY
MAPTOSAMESHORTCUT
MAPVK
@@ -1050,15 +1184,14 @@ Markdig
markdownpreviewhandler
MARKDOWNPREVIEWHANDLERCPP
Markovic
-Marquesas
martinchrzan
martinmoene
-Mato
Maximizable
MAXIMIZEBOX
MAXSHORTCUTSIZE
maxversiontested
Mbits
+MBR
MBs
MBUTTON
MBUTTONDBLCLK
@@ -1079,19 +1212,22 @@ Mega
Melman
MENUITEMINFO
MENUITEMINFOW
-menurc
+MERGECOPY
+MERGEPAINT
Metadatas
metafile
mfapi
mfc
-mfcm
mfidl
mfobjects
mfplat
Mfsensorgroup
mftransform
+Mgmt
mic
microsoft
+MIDDLEDOWN
+MIDDLEUP
Midl
mii
MIIM
@@ -1106,11 +1242,12 @@ miniz
minlevel
MINORVERSION
Miracast
-Mishkeegogamang
mjpg
mkd
mkdn
mlcfg
+mmc
+mmcexe
MMdd
mmdeviceapi
mmi
@@ -1120,8 +1257,7 @@ mockapi
MODECHANGE
modernwpf
MODESPRUNED
-Moldova
-Mongala
+MONITORENUMPROC
MONITORINFO
MONITORINFOEX
MONITORINFOEXW
@@ -1145,11 +1281,9 @@ mrw
msbuild
msc
msclr
-mscordaccore
-mscordbi
mscorlib
-mscorrc
msdata
+msdax
msedge
MSGFLT
MSIFASTINSTALL
@@ -1161,7 +1295,6 @@ MSIXCA
MSLLHOOKSTRUCT
Mso
msp
-msquic
msrc
msstore
mst
@@ -1171,15 +1304,12 @@ MTND
Mul
MULTIPLEUSE
multizone
-Mundrabilla
mvvm
myfile
MYICON
-MYTZ
+mysql
NAMECHANGE
nameof
-Navassa
-navigatetostring
NCACTIVATE
ncc
NCCALCSIZE
@@ -1195,12 +1325,12 @@ NCMBUTTONUP
NCMOUSELEAVE
NCMOUSEMOVE
NCol
+ncpa
NCPAINT
NCRBUTTONDBLCLK
NCRBUTTONDOWN
NCRBUTTONUP
NCRENDERING
-Ndombe
ndp
NEEDDISPATCH
neighborings
@@ -1212,7 +1342,6 @@ netcpl
netframework
netsetup
netsh
-netstandard
Neue
newcolor
newdev
@@ -1225,11 +1354,13 @@ nielslaute
NIF
NLD
nlog
+nls
NLSTEXT
NOACTIVATE
NOAGGREGATION
NOASYNC
NOCLOSEPROCESS
+NOCOALESCE
NOCOPYBITS
nodeca
nodiscard
@@ -1238,13 +1369,13 @@ NOINHERITLAYOUT
NOINTERFACE
NOLINKINFO
NOMINMAX
+NOMIRRORBITMAP
NOMOVE
NONAME
nonclient
NONCONVERT
NONELEVATED
NONINFRINGEMENT
-nonpackaged
nonstd
NOOPEN
NOOWNERZORDER
@@ -1258,7 +1389,6 @@ NOREPOSITION
norestart
NORMALDISPLAY
NORMALUSER
-Noronha
NOSEARCH
NOSENDCHANGING
NOSIZE
@@ -1270,6 +1400,8 @@ notmatch
Noto
NOTOPMOST
NOTRACK
+NOTSRCCOPY
+NOTSRCERASE
NOUPDATE
NOZORDER
NPH
@@ -1277,15 +1409,13 @@ NResize
nrw
NTAPI
ntdll
-NTFS
+ntfs
NTSTATUS
nugets
nullonfailure
numberbox
NUMLOCK
-NUMPAD
-Nunavut
-Nusa
+numpad
nwc
Objbase
OBJID
@@ -1305,9 +1435,7 @@ oldpath
oldtheme
oleaut
OLECHAR
-oledb
-oledbcommand
-oledbconnection
+OLEDB
OLIVEGREEN
onebranch
onenote
@@ -1326,6 +1454,7 @@ OPTIMIZEFORINVOKE
ORAW
ori
ORPHANEDDIALOGTITLE
+ORSCANS
oss
ostr
OSVERSIONINFOEX
@@ -1357,8 +1486,13 @@ PARENTRELATIVEPARSING
PArgb
parray
PARTIALCONFIRMATIONDIALOGTITLE
+pascaligo
+pasteplain
+PATCOPY
pathcch
Pathto
+PATINVERT
+PATPAINT
PAUDIO
pbc
pbgra
@@ -1380,8 +1514,10 @@ PDWORD
pedrolamas
pef
PElems
+Pels
PERCEIVEDFLAG
Percision
+perfmon
pesi
petabyte
peteblois
@@ -1390,6 +1526,7 @@ pfn
pfo
pft
pgp
+pgsql
pguid
PHANDLE
PHANDLER
@@ -1404,9 +1541,7 @@ PINDIR
pinfo
pinvoke
pipename
-Pitcairn
PKBDLLHOOKSTRUCT
-Pkcs
PKEY
plib
PLK
@@ -1416,14 +1551,16 @@ plocm
plugins
pluginsmodel
PMSIHANDLE
-Pohnpei
+Pnp
Popups
POPUPWINDOW
posix
+postiats
poweraccent
powerlauncher
POWEROCR
powerpreview
+powerquery
powerrename
POWERRENAMECONTEXTMENU
powerrenameinput
@@ -1431,6 +1568,7 @@ POWERRENAMETEST
powertoy
POWERTOYNAME
powertoyssetup
+powertoysusersetup
Powrprof
ppenum
ppidl
@@ -1453,7 +1591,7 @@ Preinstalled
prevhost
Previer
previewer
-previewhandlerframeinfo
+PREVIEWHANDLERFRAMEINFO
previewpane
previouscamera
PREVIOUSINSTALLFOLDER
@@ -1462,8 +1600,8 @@ prevpane
PRGBA
prgms
pri
-Primorsky
PRINTCLIENT
+printmanagement
prm
proactively
PROCESSKEY
@@ -1518,10 +1656,8 @@ QITAB
QITABENT
qps
QUERYENDSESSION
-queryfocus
QUERYOPEN
QUEUESYNC
-Quic
Quickime
QUNS
qwertyuiopasdfghjklzxcvbnm
@@ -1549,8 +1685,8 @@ RECTDESTINATION
RECTL
rectp
rects
-recyclebin
redirectedfrom
+redis
Redist
redistributable
reencode
@@ -1558,16 +1694,21 @@ reencoded
REFCLSID
REFGUID
REFIID
+Refreshable
REGCLS
regedit
regfile
REGFILTER
REGFILTERPINS
REGISTERCLASSFAILED
-registerhotkey
+REGISTRYHEADER
registrypath
+registrypreview
+REGISTRYPREVIEWEXT
+registryroot
regkey
REGPINTYPES
+regroot
regsvr
reinit
REINSTALLMODE
@@ -1577,6 +1718,7 @@ remappings
REMAPSUCCESSFUL
REMAPUNSUCCESSFUL
Remotable
+Removedir
Removelnk
renamable
RENAMEONCOLLISION
@@ -1588,9 +1730,9 @@ rescap
resgen
resheader
resizers
+RESIZETOFIT
resmimetype
RESOURCEID
-resourcemanager
RESTORETOMAXIMIZED
restrictedcapabilities
restrictederrorinfo
@@ -1611,7 +1753,9 @@ rgs
rhs
ricardosantos
RIDEV
+RIGHTDOWN
RIGHTSCROLLBAR
+RIGHTUP
riid
RKey
RLO
@@ -1621,8 +1765,8 @@ roadmap
robmensching
Roboto
rooler
+rop
roslyn
-Rothera
roundf
ROUNDSMALL
Rpc
@@ -1630,11 +1774,11 @@ RRF
rrr
RSAT
rshift
+rsop
Rsp
Rstrtmgr
RTB
RTLREADING
-RTSS
ruleset
runas
rundll
@@ -1642,11 +1786,11 @@ rungameid
RUNLEVEL
runsettings
runtimeclass
-runtimeconfig
+runtimedepsjsonpath
runtimeobject
runtimepack
runtimes
-rus
+RUS
Rutkas
RValue
rvm
@@ -1661,10 +1805,10 @@ SAFEARRAY
safeprojectname
SAMEKEYPREVIOUSLYMAPPED
SAMESHORTCUTPREVIOUSLYMAPPED
+Santossio
SAVEFAILED
scancode
scanled
-Schd
schedtasks
SCID
Scip
@@ -1678,10 +1822,9 @@ sddl
SDKDDK
sdns
searchterm
-secauthz
+secpol
Secur
-securityoverview
-segoe
+Segoe
Sekan
SENDCHANGE
sendinput
@@ -1718,14 +1861,12 @@ shellex
SHELLEXECUTEINFO
SHELLEXECUTEINFOW
shellscalingapi
-shemptyrecyclebina
SHFILEINFO
SHGFI
Shgno
Shl
shldisp
shlobj
-Shlw
shlwapi
shmem
shobjidl
@@ -1750,7 +1891,7 @@ SHOWMINNOACTIVE
SHOWNA
SHOWNOACTIVATE
SHOWNORMAL
-showwindow
+SHOWWINDOW
shtypes
SICHINT
sid
@@ -1797,10 +1938,13 @@ spsi
spsia
spsrm
spsv
+SRCAND
SRCCOPY
+SRCERASE
Srch
+SRCINVERT
+SRCPAINT
sre
-Srednekolymsk
SResize
srf
SRGB
@@ -1810,7 +1954,6 @@ srw
srwlock
sse
ssf
-Ssl
STACKFRAME
stackoverflow
stackpanel
@@ -1821,7 +1964,7 @@ STARTUPINFO
STARTUPINFOEX
STARTUPINFOW
startupscreen
-statflag
+STATFLAG
STATICEDGE
STATSTG
stdafx
@@ -1859,9 +2002,7 @@ subkey
SUBLANG
subquery
subresource
-Sul
Superbar
-Suri
sut
SVE
SVGIn
@@ -1881,17 +2022,16 @@ SYSCOMMAND
SYSDEADCHAR
sysdm
SYSICONINDEX
-sysinfo
SYSKEY
syskeydown
-syskeyup
+SYSKEYUP
SYSMENU
SYSTEMAPPS
systemroot
SYSTEMTIME
+systemverilog
sysvol
Tadele
-Tajikistan
talynone
TApp
TApplication
@@ -1909,6 +2049,7 @@ taskkill
tasklist
taskschd
tchar
+tcl
Tcollab
tcs
tcscpy
@@ -1917,6 +2058,7 @@ tdbuild
TDefault
TDevice
telem
+telephon
Templated
templatenamespace
Tenggara
@@ -1943,6 +2085,7 @@ timeutil
timezones
titlebar
Titlecase
+TKey
TLayout
tlb
tlbimp
@@ -1955,7 +2098,6 @@ toolkitconverters
Toolset
toolwindow
TOPDOWNDIB
-tostring
TOUCHEVENTF
TOUCHINPUT
touchpad
@@ -1963,14 +2105,13 @@ Towindow
tracelogging
traies
transicc
-Transnistria
TRAYMOUSEMESSAGE
triaging
TRK
trl
-Tshuapa
+Tsd
+TServer
TStr
-Tuva
TValue
TWF
tymed
@@ -1984,20 +2125,17 @@ TYPESHORTCUT
UAC
UAL
uap
-uapmanifestschema
+uby
udit
Udk
-Udmurtia
Udp
uefi
UHash
UIA
-uiauto
uid
UIEx
uipi
UIs
-Ulaanbaatar
ULARGE
ULONGLONG
UMsg
@@ -2027,7 +2165,6 @@ UOffset
Updatelayout
UPGRADINGPRODUCTCODE
Uptool
-Urville
Usb
USEDEFAULT
USEFILEATTRIBUTES
@@ -2042,13 +2179,13 @@ Utc
utf
UType
uuidof
-Uvs
uwp
uxtheme
UYVY
vabdq
validmodulename
Vanara
+variantassignment
VARTYPE
vcamp
vccorlib
@@ -2083,7 +2220,7 @@ VIDEOINFOHEADER
viewbox
viewmodel
vih
-virtualkey
+VIRTUALDESK
visiblecolorformats
Visibletrue
VKey
@@ -2113,7 +2250,7 @@ WANTPALM
wbem
wbemuuid
WBounds
-wca
+Wca
wcautil
WCE
wcex
@@ -2132,6 +2269,7 @@ website
wekyb
Wevtapi
wgpocpl
+WHITEONBLACK
whitespaces
WIC
wifi
@@ -2139,7 +2277,6 @@ wikipedia
wildcards
winapi
winappdriver
-winauto
wincodec
Wincodecsdk
wincolor
@@ -2173,8 +2310,7 @@ winkey
WINL
winmd
winmm
-winmsg
-winnt
+WINNT
winres
winrt
winsdk
@@ -2184,7 +2320,7 @@ winternl
WINTHRESHOLD
winui
winuiex
-winuser
+WINVER
winxamlmanager
wistd
withinrafael
@@ -2199,6 +2335,7 @@ wmain
Wman
wmi
WMICIM
+wmimgmt
WMKEYDOWN
WMKEYUP
wmp
@@ -2217,7 +2354,7 @@ workspaces
wox
wparam
wpf
-wpfgfx
+wpfdepsjsonpath
wpftmp
wpr
wprp
@@ -2229,6 +2366,7 @@ writefile
Wrk
wrl
WScan
+wscui
wsf
wsh
wsl
@@ -2240,7 +2378,6 @@ wtoi
WTS
wtsapi
WTSAT
-wtypes
Wubi
wuceffectsi
WVC
@@ -2248,6 +2385,7 @@ WVk
Wwan
Wwanpp
XAttribute
+XAxis
Xbox
XBUTTON
XBUTTONDBLCLK
@@ -2255,7 +2393,9 @@ XBUTTONDOWN
XBUTTONUP
xcopy
XDocument
+XDOWN
XElement
+xfd
XFile
XIncrement
XLoc
@@ -2265,14 +2405,18 @@ XPixel
XResource
xsi
XStr
+XUP
XVIRTUALSCREEN
-Yamalia
+YAxis
+Yeet
YIncrement
yinle
yinwang
yinyue
YOffset
+ypescript
YQuantized
+YResolution
YStr
YUY
yuyoyuppe
@@ -2280,7 +2424,6 @@ YUYV
YVIRTUALSCREEN
YVU
YVYU
-Zabaykalsky
ZEROINIT
ZIndex
zipfile
@@ -2288,7 +2431,5 @@ zipfolder
zonable
zoneset
Zoneszonabletester
-Zonev
-zopfli
Zykova
zzz
diff --git a/.github/actions/spell-check/patterns.txt b/.github/actions/spell-check/patterns.txt
index 774349778a..f17c5fb2aa 100644
--- a/.github/actions/spell-check/patterns.txt
+++ b/.github/actions/spell-check/patterns.txt
@@ -56,12 +56,15 @@ https?://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
/gist\.github\.com/[^/]+/[0-9a-f]+
# msdn
-\b(?:download\.visualstudio|docs|msdn)\.microsoft\.com/[-_a-zA-Z0-9()=./]*
+\b(?:download\.visualstudio|docs|msdn|learn)\.microsoft\.com/[-_a-zA-Z0-9()=./]*
# medium
link\.medium\.com/[a-zA-Z0-9]+
\bmedium\.com/\@[^/]+/[-\w]+
+# experimentation urls
+https?://default\.exp-tas\.com/[-_a-zA-Z0-9/]*
+
publicKeyToken=(['"]|)[0-9a-f]+\g{-1}
\@sha256:[0-9a-f]{64}\b
diff --git a/.github/workflows/package-submissions.yml b/.github/workflows/package-submissions.yml
index 5ef20fec67..e99a5e7378 100644
--- a/.github/workflows/package-submissions.yml
+++ b/.github/workflows/package-submissions.yml
@@ -1,4 +1,4 @@
-name: Submit Microsoft.PowerToys package to Windows Package Manager Community Repository
+name: Submit Microsoft.PowerToys package to Windows Package Manager Community Repository
# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml
on:
@@ -7,24 +7,25 @@ on:
types: [published]
jobs:
-
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Submit package to Windows Package Manager Community Repository
run: |
-
+
$wingetPackage = "Microsoft.PowerToys"
$gitToken = "${{ secrets.PT_WINGET }}"
-
+
$github = Invoke-RestMethod -uri "https://api.github.com/repos/Microsoft/PowerToys/releases"
-
+
$targetRelease = $github | Where-Object -Property name -match 'Release'| Select -First 1
- $installerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*x64' | Select -ExpandProperty browser_download_url
- $installerUrlArm = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*arm64' | Select -ExpandProperty browser_download_url
+ $installerUserX64Url = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysUserSetup.*x64' | Select -ExpandProperty browser_download_url
+ $installerMachineX64Url = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*x64' | Select -ExpandProperty browser_download_url
+ $installerUserArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysUserSetup.*arm64' | Select -ExpandProperty browser_download_url
+ $installerMachineArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*arm64' | Select -ExpandProperty browser_download_url
$ver = $targetRelease.tag_name.Trim("v")
-
+
# getting latest wingetcreate file
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
- .\wingetcreate.exe update $wingetPackage -s -v $ver -u $installerUrl $installerUrlArm -t $gitToken
+ .\wingetcreate.exe update $wingetPackage -s -v $ver -u $installerUserX64Url $installerMachineX64Url $installerUserArmUrl $installerMachineArmUrl -t $gitToken
diff --git a/.gitignore b/.gitignore
index 14c1e39737..cbd74e790c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -345,6 +345,3 @@ src/common/Telemetry/*.etl
/src/modules/previewpane/SvgThumbnailProvider/$(SolutionDir)$(Platform)/$(Configuration)/modules/FileExplorerPreview/SvgThumbnailProvider.xml
/src/modules/powerrename/ui/RCa24464
/src/modules/powerrename/ui/RCb24464
-
-# Generated installer file for Monaco source files.
-/installer/PowerToysSetup/MonacoSRC.wxs
diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json
index 5db90e70b6..01f6d011c6 100644
--- a/.pipelines/ESRPSigning_core.json
+++ b/.pipelines/ESRPSigning_core.json
@@ -23,6 +23,7 @@
"PowerToys.Settings.UI.Lib.dll",
"PowerToys.GPOWrapper.dll",
"PowerToys.GPOWrapperProjection.dll",
+ "PowerToys.AllExperiments.dll",
"modules\\AlwaysOnTop\\PowerToys.AlwaysOnTop.exe",
"modules\\AlwaysOnTop\\PowerToys.AlwaysOnTopModuleInterface.dll",
@@ -35,6 +36,8 @@
"modules\\PowerOCR\\PowerToys.PowerOCR.dll",
"modules\\PowerOCR\\PowerToys.PowerOCR.exe",
+ "modules\\PastePlain\\PowerToys.PastePlainModuleInterface.dll",
+
"modules\\Awake\\PowerToys.AwakeModuleInterface.dll",
"modules\\Awake\\PowerToys.Awake.exe",
"modules\\Awake\\PowerToys.Awake.dll",
@@ -125,7 +128,6 @@
"modules\\launcher\\Plugins\\Service\\Microsoft.PowerToys.Run.Plugin.Service.dll",
"modules\\launcher\\Plugins\\System\\Microsoft.PowerToys.Run.Plugin.System.dll",
"modules\\launcher\\Plugins\\TimeDate\\Microsoft.PowerToys.Run.Plugin.TimeDate.dll",
- "modules\\launcher\\Plugins\\TimeZone\\Microsoft.PowerToys.Run.Plugin.TimeZone.dll",
"modules\\launcher\\Plugins\\WebSearch\\Community.PowerToys.Run.Plugin.WebSearch.dll",
"modules\\launcher\\Plugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll",
@@ -136,7 +138,10 @@
"modules\\MouseUtils\\PowerToys.FindMyMouse.dll",
"modules\\MouseUtils\\PowerToys.MouseHighlighter.dll",
+ "modules\\MouseUtils\\PowerToys.MouseJump.dll",
"modules\\MouseUtils\\PowerToys.MousePointerCrosshairs.dll",
+ "modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.dll",
+ "modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.exe",
"modules\\PowerAccent\\PowerAccent.Core.dll",
"modules\\PowerAccent\\PowerToys.PowerAccent.dll",
@@ -149,6 +154,10 @@
"modules\\PowerRename\\PowerToys.PowerRenameContextMenu.dll",
"modules\\PowerRename\\PowerRenameContextMenuPackage.msix",
+ "modules\\RegistryPreview\\PowerToys.RegistryPreviewExt.dll",
+ "modules\\RegistryPreview\\PowerToys.RegistryPreview.dll",
+ "modules\\RegistryPreview\\PowerToys.RegistryPreview.exe",
+
"modules\\ShortcutGuide\\ShortcutGuide\\PowerToys.ShortcutGuide.exe",
"modules\\ShortcutGuide\\ShortcutGuideModuleInterface\\PowerToys.ShortcutGuideModuleInterface.dll",
@@ -209,6 +218,8 @@
"Mono.Cecil.Mdb.dll",
"Mono.Cecil.Pdb.dll",
"Mono.Cecil.Rocks.dll",
+ "Newtonsoft.Json.dll",
+ "Newtonsoft.Json.Bson.dll",
"NLog.dll",
"HtmlAgilityPack.dll",
"Markdig.Signed.dll",
@@ -240,11 +251,14 @@
"modules\\PowerAccent\\Vanara.PInvoke.Shell32.dll",
"modules\\PowerAccent\\Vanara.PInvoke.ShlwApi.dll",
"modules\\PowerAccent\\Vanara.PInvoke.User32.dll",
+ "modules\\RegistryPreview\\clrcompression.dll",
+ "modules\\RegistryPreview\\Microsoft.Graphics.Canvas.Interop.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.Core.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.WinForms.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.Wpf.dll",
"modules\\FileExplorerPreview\\WebView2Loader.dll",
"modules\\Hosts\\Microsoft.Graphics.Canvas.Interop.dll",
+ "modules\\Hosts\\clrcompression.dll",
"modules\\launcher\\e_sqlite3.dll",
"modules\\launcher\\LazyCache.dll",
"modules\\launcher\\SQLitePCLRaw.batteries_v2.dll",
diff --git a/.pipelines/ESRPSigning_installer.json b/.pipelines/ESRPSigning_installer.json
index dea4efc7f4..b20e2cdc82 100644
--- a/.pipelines/ESRPSigning_installer.json
+++ b/.pipelines/ESRPSigning_installer.json
@@ -5,8 +5,8 @@
{
"MatchedPath": [
"PowerToysSetupCustomActions.dll",
- "PowerToysSetup-*.exe",
- "PowerToysSetup-*.msi"
+ "PowerToys*Setup-*.exe",
+ "PowerToys*Setup-*.msi"
],
"SigningInfo": {
"Operations": [
diff --git a/.pipelines/ci/templates/build-powertoys-steps.yml b/.pipelines/ci/templates/build-powertoys-steps.yml
index 26754babe8..0da849f2bb 100644
--- a/.pipelines/ci/templates/build-powertoys-steps.yml
+++ b/.pipelines/ci/templates/build-powertoys-steps.yml
@@ -69,7 +69,7 @@ steps:
configPath: NuGet.config
restoreSolution: PowerToys.sln
restoreDirectory: '$(Build.SourcesDirectory)\packages'
-
+
- task: VSBuild@1
displayName: 'Build PowerToys.sln'
inputs:
@@ -153,7 +153,7 @@ steps:
filePath: '$(build.sourcesdirectory)\.pipelines\installWiX.ps1'
- task: VSBuild@1
- displayName: 'Build PowerToys MSI'
+ displayName: 'Build PowerToys per-machine MSI'
inputs:
solution: '**\installer\PowerToysSetup.sln'
vsVersion: 17.0
@@ -163,7 +163,7 @@ steps:
maximumCpuCount: true
- task: VSBuild@1
- displayName: 'Build PowerToys Bootstrapper'
+ displayName: 'Build PowerToys per-machine Bootstrapper'
inputs:
solution: '**\installer\PowerToysSetup.sln'
vsVersion: 17.0
@@ -173,6 +173,43 @@ steps:
clean: false
maximumCpuCount: true
+- task: PowerShell@2
+ displayName: Clean installer dir before building per-user installer
+ inputs:
+ targetType: inline
+ script: git clean -xfd -e *exe -- .\installer\
+ pwsh: true
+
+- task: NuGetCommand@2
+ displayName: Restore NuGet packages for PowerToysSetup.sln
+ inputs:
+ command: restore
+ feedsToUse: config
+ configPath: NuGet.config
+ restoreSolution: installer\PowerToysSetup.sln
+ restoreDirectory: '$(Build.SourcesDirectory)\installer\packages'
+
+- task: VSBuild@1
+ displayName: 'Build PowerToys per-user MSI'
+ inputs:
+ solution: '**\installer\PowerToysSetup.sln'
+ vsVersion: 17.0
+ platform: '$(BuildPlatform)'
+ configuration: '$(BuildConfiguration)'
+ msbuildArgs: /t:PowerToysInstaller ${{ parameters.additionalBuildArguments }} /p:PerUser=true
+ maximumCpuCount: true
+
+- task: VSBuild@1
+ displayName: 'Build PowerToys per-user Bootstrapper'
+ inputs:
+ solution: '**\installer\PowerToysSetup.sln'
+ vsVersion: 17.0
+ platform: '$(BuildPlatform)'
+ configuration: '$(BuildConfiguration)'
+ msbuildArgs: /t:PowerToysBootstrapper ${{ parameters.additionalBuildArguments }} /p:PerUser=true
+ clean: false
+ maximumCpuCount: true
+
# directly not doing WinAppDriver testing
- task: VSTest@2
displayName: 'MS Tests'
@@ -201,13 +238,13 @@ steps:
**\Wox.Test.dll
**\Microsoft.PowerToys.Run.Plugin.System.UnitTests.dll
**\Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests.dll
- **\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests.dll
**\Microsoft.Plugin.WindowsTerminal.UnitTests.dll
**\Microsoft.Plugin.WindowWalker.UnitTests.dll
**\PreviewPaneUnitTests.dll
**\UnitTests-SvgThumbnailProvider.dll
**\UnitTests-SvgPreviewHandler.dll
**\PowerToys.Hosts.Tests.dll
+ **\MouseJumpUI.UnitTests.dll
!**\obj\**
!**\ref\**
@@ -227,10 +264,17 @@ steps:
**\powerpreviewTest.dll
**\UnitTests-FancyZones.dll
!**\obj\**
-
+
+- task: PowerShell@2
+ displayName: Trigger dotnet welcome message so that it does not cause errors on other scripts
+ inputs:
+ targetType: 'inline'
+ script: |
+ dotnet list $(build.sourcesdirectory)\src\common\Common.UI\Common.UI.csproj package
+
- task: PowerShell@2
displayName: Verifying Notice.md and Nuget packages match
inputs:
filePath: '$(build.sourcesdirectory)\.pipelines\verifyNoticeMdAgainstNugetPackages.ps1'
arguments: -path '$(build.sourcesdirectory)\'
- pwsh: true
\ No newline at end of file
+ pwsh: true
diff --git a/.pipelines/installWiX.ps1 b/.pipelines/installWiX.ps1
index 18a81c93d3..ab770b8bf5 100644
--- a/.pipelines/installWiX.ps1
+++ b/.pipelines/installWiX.ps1
@@ -1,7 +1,7 @@
$ProgressPreference = 'SilentlyContinue'
-$WixDownloadUrl = "https://github.com/JaneaSystems/wix3/releases/download/wix3-3.14.0.6526/wix314.exe"
-$WixBinariesDownloadUrl = "https://github.com/JaneaSystems/wix3/releases/download/wix3-3.14.0.6526/wix314-binaries.zip"
+$WixDownloadUrl = "https://wixtoolset.org/downloads/v3.14.0.6526/wix314.exe"
+$WixBinariesDownloadUrl = "https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip"
# Download WiX binaries and verify their hash sums
Invoke-WebRequest -Uri $WixDownloadUrl -OutFile "$($ENV:Temp)\wix314.exe"
diff --git a/.pipelines/installer-steps.yml b/.pipelines/installer-steps.yml
new file mode 100644
index 0000000000..6ab7e01009
--- /dev/null
+++ b/.pipelines/installer-steps.yml
@@ -0,0 +1,141 @@
+parameters:
+ - name: versionNumber
+ type: string
+ default: "0.0.1"
+ - name: perUserArg
+ type: string
+ default: "false"
+ - name: buildSubDir
+ type: string
+ default: "MachineSetup"
+ - name: installerPrefix
+ type: string
+ default: "PowerToysSetup"
+
+steps:
+ - task: VSBuild@1
+ displayName: Build PowerToysSetupCustomActions DLL # This dll needs to be build and signed before building the MSI.
+ inputs:
+ solution: "**/installer/PowerToysSetup.sln"
+ vsVersion: 17.0
+ msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog /t:PowerToysSetupCustomActions /p:RunBuildEvents=true /p:PerUser=${{parameters.perUserArg}}
+ platform: $(BuildPlatform)
+ configuration: $(BuildConfiguration)
+ clean: true
+ maximumCpuCount: true
+
+ - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
+ displayName: Sign PowerToysSetupCustomActions DLL
+ inputs:
+ ConnectedServiceName: "Terminal/Console/WinAppDriver Team Code Signing Connection"
+ FolderPath: 'installer/PowerToysSetupCustomActions/$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}'
+ signType: batchSigning
+ batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
+ ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
+
+ ## INSTALLER START
+ #### MSI BUILDING AND SIGNING
+ - task: VSBuild@1
+ displayName: Build MSI
+ inputs:
+ solution: "**/installer/PowerToysSetup.sln"
+ vsVersion: 17.0
+ msbuildArgs: /p:CIBuild=true /target:PowerToysInstaller /bl:$(Build.SourcesDirectory)\msbuild.binlog /p:RunBuildEvents=false /p:PerUser=${{parameters.perUserArg}}
+ platform: $(BuildPlatform)
+ configuration: $(BuildConfiguration)
+ clean: false # don't undo our hard work above by deleting the CustomActions dll
+ maximumCpuCount: true
+
+ - task: CmdLine@2
+ displayName: "Extracting MSI to verify contents"
+ inputs:
+ script: |
+ "C:\Program Files (x86)\WiX Toolset v3.14\bin\dark.exe" -x $(build.sourcesdirectory)\extractedMsi installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}\${{parameters.installerPrefix}}-${{ parameters.versionNumber }}-$(BuildPlatform).msi
+ dir $(build.sourcesdirectory)\extractedMsi
+
+ # Did we sign all files
+ - task: PowerShell@1
+ displayName: Verifying entire build is signed and version set
+ inputs:
+ scriptName: .pipelines/versionAndSignCheck.ps1
+ arguments: -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
+
+ - task: PowerShell@1
+ displayName: Verifying MSI Custom Actions DLL is signed
+ inputs:
+ scriptName: .pipelines/versionAndSignCheck.ps1
+ arguments: -targetDir '$(build.sourcesdirectory)\extractedMsi\Binary'
+
+ - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
+ displayName: Sign MSI
+ inputs:
+ ConnectedServiceName: "Terminal/Console/WinAppDriver Team Code Signing Connection"
+ FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}'
+ signType: batchSigning
+ batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
+ ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
+ #### END MSI
+ #### BOOTSTRAP BUILDING AND SIGNING
+
+ - task: VSBuild@1
+ displayName: Build Bootstrapper
+ inputs:
+ solution: "**/installer/PowerToysSetup.sln"
+ vsVersion: 17.0
+ msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog /t:PowerToysBootstrapper /p:PerUser=${{parameters.perUserArg}}
+ platform: $(BuildPlatform)
+ configuration: $(BuildConfiguration)
+ clean: false # don't undo our hard work above by deleting the MSI
+ maximumCpuCount: true
+
+ - task: CmdLine@2
+ displayName: "Insignia: Extract Engine from Bundle"
+ inputs:
+ script: '"C:\Program Files (x86)\WiX Toolset v3.14\bin\insignia.exe" -ib installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}\${{parameters.installerPrefix}}-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\engine.exe'
+
+ - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
+ displayName: "ESRP CodeSigning (Engine)"
+ inputs:
+ ConnectedServiceName: "Terminal/Console/WinAppDriver Team Code Signing Connection"
+ FolderPath: "installer"
+ Pattern: engine.exe
+ signConfigType: inlineSignParams
+ inlineOperation: |
+ [
+ {
+ "KeyCode": "CP-230012",
+ "OperationCode": "SigntoolSign",
+ "Parameters": {
+ "OpusName": "Microsoft",
+ "OpusInfo": "http://www.microsoft.com",
+ "FileDigest": "/fd \"SHA256\"",
+ "PageHash": "/NPH",
+ "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
+ },
+ "ToolName": "sign",
+ "ToolVersion": "1.0"
+ },
+ {
+ "KeyCode": "CP-230012",
+ "OperationCode": "SigntoolVerify",
+ "Parameters": {},
+ "ToolName": "sign",
+ "ToolVersion": "1.0"
+ }
+ ]
+
+ - task: CmdLine@2
+ displayName: "Insignia: Merge Engine into Bundle"
+ inputs:
+ script: '"C:\Program Files (x86)\WiX Toolset v3.14\bin\insignia.exe" -ab installer\engine.exe installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}\${{parameters.installerPrefix}}-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}\${{parameters.installerPrefix}}-${{ parameters.versionNumber }}-$(BuildPlatform).exe'
+
+ - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
+ displayName: Sign Bootstrapper
+ inputs:
+ ConnectedServiceName: "Terminal/Console/WinAppDriver Team Code Signing Connection"
+ FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)\${{parameters.buildSubDir}}'
+ signType: batchSigning
+ batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
+ ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
+ #### END BOOTSTRAP
+ ## END INSTALLER
diff --git a/.pipelines/release-nuget.config b/.pipelines/release-nuget.config
index e1d43f2b79..822b4f137c 100644
--- a/.pipelines/release-nuget.config
+++ b/.pipelines/release-nuget.config
@@ -4,6 +4,12 @@
+
+
+
+
+
+
diff --git a/.pipelines/release.yml b/.pipelines/release.yml
index 01665c74c1..5da718fd27 100644
--- a/.pipelines/release.yml
+++ b/.pipelines/release.yml
@@ -23,6 +23,7 @@ parameters:
variables:
IsPipeline: 1 # The installer uses this to detect whether it should pick up localizations
SkipCppCodeAnalysis: 1 # Skip the code analysis to speed up release CI. It runs on PR CI, anyway
+ IsExperimentationLive: 1 # The build and installer use this to turn on experimentation
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
@@ -174,17 +175,6 @@ jobs:
clean: true
maximumCpuCount: true
- - task: VSBuild@1
- displayName: Build PowerToysSetupCustomActions
- inputs:
- solution: '**/installer/PowerToysSetup.sln'
- vsVersion: 17.0
- msbuildArgs: /target:PowerToysSetupCustomActions /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
- platform: $(BuildPlatform)
- configuration: $(BuildConfiguration)
- clean: true
- maximumCpuCount: true
-
- task: VSBuild@1
displayName: Publish Settings for Packaging
inputs:
@@ -312,29 +302,10 @@ jobs:
configuration: $(BuildConfiguration)
maximumCpuCount: true
- - task: VSBuild@1
- displayName: Build PowerToysSetupCustomActions DLL # This dll needs to be build and signed before building the MSI.
- inputs:
- solution: '**/installer/PowerToysSetup.sln'
- vsVersion: 17.0
- msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog /t:PowerToysSetupCustomActions /p:RunBuildEvents=true
- platform: $(BuildPlatform)
- configuration: $(BuildConfiguration)
- maximumCpuCount: true
-
#### MAIN SIGNING AREA
# reference https://dev.azure.com/microsoft/Dart/_git/AppDriver?path=/ESRPSigning.json&version=GBarm64-netcore&_a=contents for winappdriver
# https://dev.azure.com/microsoft/Dart/_git/AppDriver?path=/CIPolicy.xml&version=GBarm64-netcore&_a=contents
- - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
- displayName: Sign PowerToysSetupCustomActions DLL
- inputs:
- ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
- FolderPath: 'installer/PowerToysSetupCustomActions/$(BuildPlatform)\$(BuildConfiguration)'
- signType: batchSigning
- batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
- ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
-
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
displayName: Sign Core PT
inputs:
@@ -355,114 +326,6 @@ jobs:
#### END SIGNING
## END MAIN
-## INSTALLER START
-#### MSI BUILDING AND SIGNING
- - task: VSBuild@1
- displayName: Build MSI
- inputs:
- solution: '**/installer/PowerToysSetup.sln'
- vsVersion: 17.0
- msbuildArgs: /p:CIBuild=true /target:PowerToysInstaller /bl:$(Build.SourcesDirectory)\msbuild.binlog /p:RunBuildEvents=false
- platform: $(BuildPlatform)
- configuration: $(BuildConfiguration)
- clean: false # don't undo our hard work above by deleting the CustomActions dll
- maximumCpuCount: true
-
- - task: CmdLine@2
- displayName: 'Extracting MSI to verify contents'
- inputs:
- script: |
- "C:\Program Files (x86)\WiX Toolset v3.14\bin\dark.exe" -x $(build.sourcesdirectory)\extractedMsi installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).msi
- dir $(build.sourcesdirectory)\extractedMsi
-
-# Did we sign all files
- - task: PowerShell@1
- displayName: Verifying entire build is signed and version set
- inputs:
- scriptName: .pipelines/versionAndSignCheck.ps1
- arguments: -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
-
- - task: PowerShell@1
- displayName: Verifying MSI Custom Actions DLL is signed
- inputs:
- scriptName: .pipelines/versionAndSignCheck.ps1
- arguments: -targetDir '$(build.sourcesdirectory)\extractedMsi\Binary'
-
- - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
- displayName: Sign MSI
- inputs:
- ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
- FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)'
- signType: batchSigning
- batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
- ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
-#### END MSI
-
-#### BOOTSTRAP BUILDING AND SIGNING
- - task: VSBuild@1
- displayName: Build Bootstrapper
- inputs:
- solution: '**/installer/PowerToysSetup.sln'
- vsVersion: 17.0
- msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog /t:PowerToysBootstrapper
- platform: $(BuildPlatform)
- configuration: $(BuildConfiguration)
- clean: false # don't undo our hard work above by deleting the MSI
- maximumCpuCount: true
-
- - task: CmdLine@2
- displayName: 'Insignia: Extract Engine from Bundle'
- inputs:
- script: '"C:\Program Files (x86)\WiX Toolset v3.14\bin\insignia.exe" -ib installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\engine.exe'
-
-
- - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
- displayName: 'ESRP CodeSigning (Engine)'
- inputs:
- ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
- FolderPath: 'installer'
- Pattern: engine.exe
- signConfigType: inlineSignParams
- inlineOperation: |
- [
- {
- "KeyCode": "CP-230012",
- "OperationCode": "SigntoolSign",
- "Parameters": {
- "OpusName": "Microsoft",
- "OpusInfo": "http://www.microsoft.com",
- "FileDigest": "/fd \"SHA256\"",
- "PageHash": "/NPH",
- "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
- },
- "ToolName": "sign",
- "ToolVersion": "1.0"
- },
- {
- "KeyCode": "CP-230012",
- "OperationCode": "SigntoolVerify",
- "Parameters": {},
- "ToolName": "sign",
- "ToolVersion": "1.0"
- }
- ]
-
- - task: CmdLine@2
- displayName: 'Insignia: Merge Engine into Bundle'
- inputs:
- script: '"C:\Program Files (x86)\WiX Toolset v3.14\bin\insignia.exe" -ab installer\engine.exe installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe -o installer\PowerToysSetup\$(BuildPlatform)\$(BuildConfiguration)\PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform).exe'
-
- - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
- displayName: Sign Bootstrapper
- inputs:
- ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection'
- FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)'
- signType: batchSigning
- batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
- ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
-#### END BOOTSTRAP
-## END INSTALLER
-
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: binlog'
condition: failed()
@@ -513,10 +376,39 @@ jobs:
SourceFolder: $(Build.ArtifactStagingDirectory)/Symbols-$(BuildPlatform)/
RemoveSourceFolder: True
+ - template: installer-steps.yml
+ parameters:
+ versionNumber: ${{ parameters.versionNumber }}
+ perUserArg: "false"
+ buildSubDir: "MachineSetup"
+ installerPrefix: "PowerToysSetup"
+
+ - task: PowerShell@2
+ displayName: Clean installer dir before building per-user installer
+ inputs:
+ targetType: inline
+ script: git clean -xfd -e *exe -- .\installer\
+ pwsh: true
+
+ - task: NuGetCommand@2
+ displayName: NuGet restore solutions dependencies
+ inputs:
+ command: restore
+ restoreSolution: 'installer/*.sln'
+ selectOrConfig: config
+ nugetConfigPath: .pipelines/release-nuget.config
+
+ - template: installer-steps.yml
+ parameters:
+ versionNumber: ${{ parameters.versionNumber }}
+ perUserArg: "true"
+ buildSubDir: "UserSetup"
+ installerPrefix: "PowerToysUserSetup"
+
- task: CopyFiles@2
displayName: Copying setup file over
inputs:
- contents: '**/PowerToysSetup-*.exe'
+ contents: "**/PowerToys*Setup-*.exe"
flattenFolders: True
targetFolder: $(Build.ArtifactStagingDirectory)
@@ -527,20 +419,29 @@ jobs:
script: |
$p = "$(System.ArtifactsDirectory)\";
$staging = "$(Build.ArtifactStagingDirectory)\"
- $hash = ((get-item $p\*.exe | Get-FileHash).Hash);
- $plat = "hash_$(BuildPlatform).txt";
- $combinedPath = $staging + $plat;
+ $userHash = ((get-item $p\PowerToysUserSetup*.exe | Get-FileHash).Hash);
+ $machineHash = ((get-item $p\PowerToysSetup*.exe | Get-FileHash).Hash);
+ $userPlat = "hash_user_$(BuildPlatform).txt";
+ $machinePlat = "hash_machine_$(BuildPlatform).txt";
+ $combinedUserPath = $staging + $userPlat;
+ $combinedMachinePath = $staging + $machinePlat;
- echo $plat
- echo $hash
echo $p
- echo $combinedPath
+
+ echo $userPlat
+ echo $userHash
+ echo $combinedUserPath
+
+ echo $machinePlat
+ echo $machineHash
+ echo $combinedMachinePath
- $hash | out-file -filepath $combinedPath
+ $userHash | out-file -filepath $combinedUserPath
+ $machineHash | out-file -filepath $combinedMachinePath
pwsh: true
-
+
- task: PublishBuildArtifacts@1
- displayName: 'Publish Artifact: PowerToySetup'
+ displayName: "Publish Artifact: PowerToySetup"
inputs:
PathtoPublish: $(System.ArtifactsDirectory)
ArtifactName: setup-$(BuildPlatform)
diff --git a/.pipelines/verifyArm64Configuration.ps1 b/.pipelines/verifyArm64Configuration.ps1
index 6a9cdd3986..56e06c8f65 100644
--- a/.pipelines/verifyArm64Configuration.ps1
+++ b/.pipelines/verifyArm64Configuration.ps1
@@ -22,7 +22,7 @@ catch {
$solutionFile = [Microsoft.Build.Construction.SolutionFile]::Parse($solution);
$arm64SlnConfigs = $solutionFile.SolutionConfigurations | Where-Object {
- $_.PlatformName -eq "ARM64"
+ $_.PlatformName -ceq "ARM64"
};
# Should have two configurations. Debug and Release.
@@ -39,9 +39,9 @@ $projects = $solutionFile.ProjectsInOrder | Where-Object {
# Enumerate through the projects and add any project with a mismatched platform and project configuration
foreach ($project in $projects) {
foreach ($slnConfig in $arm64SlnConfigs.FullName) {
- if ($project.ProjectConfigurations.$slnConfig.FullName -ne $slnConfig) {
- $errorTable[$project.ProjectName] += @(""
- | Select-Object @{n = "Configuration"; e = { $project.ProjectConfigurations.$slnConfig.FullName } },
+ if ($project.ProjectConfigurations.$slnConfig.FullName -cne $slnConfig) {
+ $errorTable[$project.ProjectName] += @(""`
+ | Select-Object @{n = "Configuration"; e = { $project.ProjectConfigurations.$slnConfig.FullName ?? "Missing platform" } },
@{n = "ExpectedConfiguration"; e = { $slnConfig } })
}
}
diff --git a/.pipelines/verifyNoticeMdAgainstNugetPackages.ps1 b/.pipelines/verifyNoticeMdAgainstNugetPackages.ps1
index affff4c782..2ee58da745 100644
--- a/.pipelines/verifyNoticeMdAgainstNugetPackages.ps1
+++ b/.pipelines/verifyNoticeMdAgainstNugetPackages.ps1
@@ -38,6 +38,8 @@ $totalList = $projFiles | ForEach-Object -Parallel {
if($nugetTemp -is [array] -and $nugetTemp.count -gt 3)
{
+ # Need to debug this script? Uncomment this line.
+ # Write-Host $csproj "`r`n" $nugetTemp "`r`n"
$temp = New-Object System.Collections.ArrayList
$temp.AddRange($nugetTemp)
$temp.RemoveRange(0, 3)
diff --git a/.pipelines/versionAndSignCheck.ps1 b/.pipelines/versionAndSignCheck.ps1
index 6008eca3a0..c39d7eac84 100644
--- a/.pipelines/versionAndSignCheck.ps1
+++ b/.pipelines/versionAndSignCheck.ps1
@@ -1,90 +1,82 @@
[CmdletBinding()]
# todo: send in arch / conf, could send in actual path
Param(
- [Parameter(Mandatory=$True,Position=1)]
- [AllowEmptyString()]
- [string]$targetDir = $PSScriptRoot + '/../extractedMsi/File'
+ [Parameter(Mandatory = $True, Position = 1)]
+ [AllowEmptyString()]
+ [string]$targetDir = $PSScriptRoot + '/../extractedMsi/File'
)
-$DirPath = $targetDir; #this file is in pipeline, we need root.
-$items = Get-ChildItem -Path $DirPath -File -Include *.exe,*.dll,*.ttf,PTCustomActions -Recurse -Force -ErrorAction SilentlyContinue
+$DirPath = $targetDir; #this file is in pipeline, we need root.
+$items = Get-ChildItem -Path $DirPath -File -Include *.exe, *.dll, *.ttf, PTCustomActions -Recurse -Force -ErrorAction SilentlyContinue
+$versionExceptions = @(
+ "Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll",
+ "Microsoft.Windows.ApplicationModel.Resources.Projection.dll",
+ "Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll",
+ "Microsoft.Windows.AppLifecycle.Projection.dll",
+ "Microsoft.Windows.System.Power.Projection.dll",
+ "Microsoft.WindowsAppRuntime.Bootstrap.Net.dll",
+ "Microsoft.Xaml.Interactions.dll",
+ "Microsoft.Xaml.Interactivity.dll",
+ "hyjiacan.py4n.dll",
+ "Microsoft.WindowsAppRuntime.Release.Net.dll",
+ "Microsoft.Windows.Widgets.Projection.dll") -join '|';
+$nullVersionExceptions = @(
+ "codicon.ttf",
+ "e_sqlite3.dll",
+ "vcamp140_app.dll",
+ "marshal.dll",
+ "Microsoft.UI.Composition.OSSupport.dll",
+ "Microsoft.UI.Xaml.Internal.dll",
+ "Microsoft.Windows.ApplicationModel.Resources.dll",
+ "Microsoft.WindowsAppRuntime.dll",
+ "Microsoft.WindowsAppRuntime.Bootstrap.dll",
+ "MRM.dll",
+ "PushNotificationsLongRunningTask.ProxyStub.dll",
+ "WindowsAppSdk.AppxDeploymentExtensions.Desktop.dll",
+ "System.Diagnostics.EventLog.Messages.dll",
+ "Microsoft.Windows.Widgets.dll") -join '|';
$totalFailure = 0;
Write-Host $DirPath;
-if(-not (Test-Path $DirPath))
-{
+if (-not (Test-Path $DirPath)) {
Write-Host "Folder does not exist!"
}
Write-Host "Total items: " $items.Count
-if($items.Count -eq 0)
-{
- # no items means something bad happened. We should fail ASAP
- exit 1;
+if ($items.Count -eq 0) {
+ # no items means something bad happened. We should fail ASAP
+ exit 1;
}
$items | ForEach-Object {
- if($_.VersionInfo.FileVersion -eq "1.0.0.0" )
- {
- # These items are exceptions that actually have the 1.0.0.0 version.
- if ((-not $_.Name.EndsWith("Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.ApplicationModel.Resources.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.AppLifecycle.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.System.Power.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.WindowsAppRuntime.Bootstrap.Net.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Xaml.Interactions.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Xaml.Interactivity.dll")) -and
- (-not $_.Name.EndsWith("hyjiacan.py4n.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.Widgets.Projection.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.WindowsAppRuntime.Release.Net.dll"))
- )
- {
- Write-Host "Version set to 1.0.0.0: " + $_.FullName
- $totalFailure++;
- }
- }
+ if ($_.VersionInfo.FileVersion -eq "1.0.0.0" -and $_.Name -notmatch $versionExceptions) {
+ # These items are exceptions that actually have the 1.0.0.0 version.
+ Write-Host "Version set to 1.0.0.0: " + $_.FullName
+ $totalFailure++;
+ }
+ elseif ($_.VersionInfo.FileVersion -eq $null -and $_.Name -notmatch $nullVersionExceptions) {
+ # These items are exceptions that actually a version not set.
+ Write-Host "Version not set: " + $_.FullName
+ $totalFailure++;
+ }
+ elseif ($_.VersionInfo.ProductName -contains "PowerToys" -and $_.VersionInfo.LegalCopyright -notmatch "Copyright \(C\) $((Get-Date).Year)") {
+ # PowerToys assemblies that aren't updated to the current year in the copyright
+ Write-Host "Copyright year out of date: " + $_.FullName
+ $totalFailure++;
+ }
+ else {
+ $auth = Get-AuthenticodeSignature $_.FullName
+ if ($auth.SignerCertificate -eq $null) {
+ Write-Host "Not Signed: " + $_.FullName
+ $totalFailure++;
+ }
+ }
}
-$items | ForEach-Object {
- if($_.VersionInfo.FileVersion -eq $null )
- {
- # These items are exceptions that actually a version not set.
- if ((-not $_.Name.EndsWith("codicon.ttf")) -and
- (-not $_.Name.EndsWith("e_sqlite3.dll")) -and
- (-not $_.Name.EndsWith("vcamp140_app.dll")) -and
- (-not $_.Name.EndsWith("marshal.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.UI.Composition.OSSupport.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.UI.Xaml.Internal.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.Windows.ApplicationModel.Resources.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.WindowsAppRuntime.dll")) -and
- (-not $_.Name.EndsWith("Microsoft.WindowsAppRuntime.Bootstrap.dll")) -and
- (-not $_.Name.EndsWith("MRM.dll")) -and
- (-not $_.Name.EndsWith("PushNotificationsLongRunningTask.ProxyStub.dll")) -and
- (-not $_.Name.EndsWith("WindowsAppSdk.AppxDeploymentExtensions.Desktop.dll")) -and
- (-not $_.Name.EndsWith("System.Diagnostics.EventLog.Messages.dll"))
- )
- {
- Write-Host "Version not set: " + $_.FullName
- $totalFailure++;
- }
- }
+if ($totalFailure -gt 0) {
+ exit 1
}
-$items | ForEach-Object {
- $auth = Get-AuthenticodeSignature $_.FullName
- if($auth.SignerCertificate -eq $null)
- {
- Write-Host "Not Signed: " + $_.FullName
- $totalFailure++;
- }
-}
-
-if($totalFailure -gt 0)
-{
- exit 1
-}
-
-exit 0
+exit 0
\ No newline at end of file
diff --git a/COMMUNITY.md b/COMMUNITY.md
index 315498e287..8fce8b92f4 100644
--- a/COMMUNITY.md
+++ b/COMMUNITY.md
@@ -27,6 +27,9 @@ Heiko has helped triaging, discussing, and creating a substantial number of issu
### [@Jay-o-Way](https://github.com/Jay-o-Way) - Jay
Jay has helped triaging, discussing, creating a substantial number of issues and PRs.
+### [@TheJoeFin](https://github.com/TheJoeFin) - [Joe Finney](https://joefinapps.com)
+Joe has helped triaging, discussing, issues as well as fixing bugs and building features for Text Extractor.
+
### [@jsoref](https://github.com/jsoref) - [Josh Soref](https://check-spelling.dev/)
Helping keep our spelling correct :)
@@ -34,6 +37,9 @@ Helping keep our spelling correct :)
Color Picker is from Martin.
+### [@mikeclayton](https://github.com/mikeclayton) - [Michael Clayton](https://michael-clayton.com)
+Michael contributed the [initial version](https://github.com/microsoft/PowerToys/issues/23216) of the Mouse Jump tool and [a number of updates](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+author%3Amikeclayton) based on his FancyMouse utility.
+
### [@riverar](https://github.com/riverar) - [Rafael Rivera](https://withinrafael.com/)
Rafael has helped do the [upgrade from CppWinRT 1.x to 2.0](https://github.com/microsoft/PowerToys/issues/1907). He directly provided feedback to the CppWinRT team for bugs from this migration as well.
@@ -93,6 +99,10 @@ PowerToys Awake is a tool to keep your computer awake.
Niels has helped drive large sums of our update toward a new [consistent and modern UX](https://github.com/microsoft/PowerToys/issues/891). This includes the [launcher work](https://github.com/microsoft/PowerToys/issues/44), color picker UX update and [icon design](https://github.com/microsoft/PowerToys/issues/1118).
+### [@randyrants](https://github.com/randyrants) - [Randy Santossio](https://www.randyrants.com)
+
+Randy contributed Registry Preview and some very early conversations about keyboard remapping.
+
### [@oldnewthing](https://github.com/oldnewthing) - Raymond Chen
Find My Mouse is based on Raymond Chen's SuperSonar.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6c22522bb4..01d1400264 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,6 +33,10 @@ Upvote the original issue by clicking its [+😊] button and hitting 👍 (+1) i
Please comment on an issue to let us know you're interested in working on something before you start the work. Not only does this avoid multiple people unexpectedly working on the same thing at the same time but it enables us to make sure everyone is clear on what should be done to implement any new functionality. It's less work for everyone, in the long run, to establish this up front.
+### Localization issues
+
+Please file localization issues, so our internal localization team can identify and fix them. However we currently don't accept community Pull Requests fixing localization issues. Localization is handled by the internal Microsoft team only.
+
### To Spec or not to Spec
A key point is for everyone to understand the approach that will be taken. We want to be sure if anyone does work, we will accept it in. Items that are larger in scope we'll want some type of spec to understand what is being planned and have a discussion. Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
@@ -53,7 +57,7 @@ Follow the [development guidelines](https://github.com/microsoft/PowerToys/blob/
### Naming of features and functionality
-Naming should be descriptive and straight forward. We want names to be clear about functionality and usefulness moving forward.
+Naming should be descriptive and straight forward. We want names to be clear about functionality and usefulness moving forward.
### How can I become a collaborator on the PowerToys team
diff --git a/CppRuleSet.ruleset b/CppRuleSet.ruleset
index 1a59aeeeb3..2718c2e3f1 100644
--- a/CppRuleSet.ruleset
+++ b/CppRuleSet.ruleset
@@ -79,12 +79,12 @@
-
-
+
+
-
+
diff --git a/Directory.Build.props b/Directory.Build.props
index 01872028f9..3bd2b96984 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,9 +1,9 @@
- Copyright (C) 2022 Microsoft Corporation
+ Copyright (C) 2023 Microsoft Corporation
Microsoft Corp.
- Copyright (C) 2022 Microsoft Corporation
+ Copyright (C) 2023 Microsoft Corporation
PowerToys
Microsoft Corporation
en-US
@@ -29,14 +29,14 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000000..6a0575cbc9
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,65 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NOTICE.md b/NOTICE.md
index 79ac437363..54aa0e9e95 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1,4 +1,5 @@
# NOTICES AND INFORMATION
+
This software incorporates material from third parties.
- Color Picker
@@ -122,7 +123,7 @@ 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.
-### Beta Tadele's Window Walker License
+### Beta Tadele's Window Walker License
**Source**: https://github.com/betsegaw/windowwalker
@@ -167,11 +168,12 @@ SOFTWARE.
## PowerToy: Installer/Runner
### spdlog
+
**Source**: https://github.com/gabime/spdlog
The MIT License (MIT)
-Copyright (c) 2016 Gabi Melman.
+Copyright (c) 2016 Gabi Melman.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -185,7 +187,7 @@ 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
+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
@@ -195,8 +197,8 @@ THE SOFTWARE.
This software depends on the fmt lib (MIT License),
and users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst
-
### expected-lite
+
**Source**: https://github.com/martinmoene/expected-lite
Boost Software License - Version 1.0 - August 17th, 2003
@@ -224,6 +226,7 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
### zip
+
**Source**: https://github.com/kuba--/zip
This is free and unencumbered software released into the public domain.
@@ -254,6 +257,7 @@ For more information, please refer to
## Utility: Measure tool
### sse2neon
+
We adopted some functions from it.
**Source**: https://github.com/DLTcollab/sse2neon
@@ -277,7 +281,7 @@ SOFTWARE.
## NuGet Packages used by PowerToys
-- CommunityToolkit.Labs.WinUI.SettingsControls 0.0.7
+- CommunityToolkit.Labs.WinUI.SettingsControls 0.0.18
- CommunityToolkit.Mvvm 8.0.0
- CommunityToolkit.WinUI.UI 7.1.2
- CommunityToolkit.WinUI.UI.Controls 7.1.2
@@ -289,16 +293,16 @@ SOFTWARE.
- LazyCache 2.4.0
- Mages 2.0.1
- Markdig.Signed 0.27.0
-- Microsoft.CodeAnalysis.NetAnalyzers 7.0.0
+- Microsoft.CodeAnalysis.NetAnalyzers 7.0.1
- Microsoft.Data.Sqlite 7.0.0
- Microsoft.Extensions.Hosting 7.0.0
- Microsoft.NET.Test.Sdk 17.4.1
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
- Microsoft.Web.WebView2 1.0.1343.22
- Microsoft.Windows.CsWin32 0.2.46-beta
-- Microsoft.Windows.CsWinRT 2.0.0
+- Microsoft.Windows.CsWinRT 2.0.1
- Microsoft.Windows.SDK.BuildTools 10.0.22621.755
-- Microsoft.WindowsAppSDK 1.2.221116.1
+- Microsoft.WindowsAppSDK 1.2.230313.1
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
- ModernWpfUI 0.9.4
@@ -325,4 +329,4 @@ SOFTWARE.
- UnitsNet 4.145.0
- Vanara.PInvoke.Shell32 3.4.11
- Vanara.PInvoke.User32 3.4.11
-- WinUIEx 1.8.0
+- WinUIEx 2.1.0
diff --git a/PowerToys.sln b/PowerToys.sln
index 14c89ce573..0a2f63de4c 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -139,7 +139,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerLauncher", "src\module
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}
- {F44934A8-36F3-49B0-9465-3831BE041CDE} = {F44934A8-36F3-49B0-9465-3831BE041CDE}
{F8B870EB-D5F5-45BA-9CF7-A5C459818820} = {F8B870EB-D5F5-45BA-9CF7-A5C459818820}
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B} = {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}
{FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {FDB3555B-58EF-4AE6-B5F1-904719637AB4}
@@ -176,6 +175,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
src\.editorconfig = src\.editorconfig
.vsconfig = .vsconfig
Directory.Build.props = Directory.Build.props
+ Directory.Packages.props = Directory.Packages.props
Solution.props = Solution.props
EndProjectSection
EndProject
@@ -395,8 +395,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-StlThumbnailProvi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonacoPreviewHandler", "src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj", "{04B193D7-3E21-46B8-A958-89B63A8A69DE}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeZone", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeZone\Microsoft.PowerToys.Run.Plugin.TimeZone.csproj", "{F44934A8-36F3-49B0-9465-3831BE041CDE}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeDate", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.csproj", "{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests\Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests.csproj", "{FD464B4C-2F68-4D06-91E7-4208146C41F5}"
@@ -409,8 +407,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\module
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameContextMenu", "src\modules\powerrename\PowerRenameContextMenu\PowerRenameContextMenu.vcxproj", "{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests.csproj", "{C5D46169-5334-48C3-8C28-644C72832E54}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.OneNote", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.csproj", "{5A1DB2F0-0715-4B3B-98E6-79BC41540045}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerContextMenu", "src\modules\imageresizer\ImageResizerContextMenu\ImageResizerContextMenu.vcxproj", "{93B72A06-C8BD-484F-A6F7-C9F280B150BF}"
@@ -498,6 +494,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StlThumbnailProviderCpp", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SvgThumbnailProviderCpp", "src\modules\previewpane\SvgThumbnailProviderCpp\SvgThumbnailProviderCpp.vcxproj", "{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseJump", "src\modules\MouseUtils\MouseJump\MouseJump.vcxproj", "{8A08D663-4995-40E3-B42C-3F910625F284}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\MouseUtils\MouseJumpUI\MouseJumpUI.csproj", "{D962A009-834F-4EEC-AABB-430DF8F98E39}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI.UnitTests", "src\modules\MouseUtils\MouseJumpUI.UnitTests\MouseJumpUI.UnitTests.csproj", "{D9C5DE64-6849-4278-91AD-9660AECF2876}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pasteplain", "pasteplain", "{9873BA05-4C41-4819-9283-CF45D795431B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PastePlainModuleInterface", "src\modules\pasteplain\PastePlainModuleInterface\PastePlainModuleInterface.vcxproj", "{FC373B24-3293-453C-AAF5-CF2909DCEE6A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreviewUI", "src\modules\registrypreview\RegistryPreviewUI\RegistryPreviewUI.csproj", "{FD86C06A-FB54-4D5E-9831-1CDADF60D45F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegistryPreviewExt", "src\modules\registrypreview\RegistryPreviewExt\RegistryPreviewExt.vcxproj", "{697C6AF9-0A48-49A9-866C-67DA12384015}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RegistryPreview", "RegistryPreview", "{929C1324-22E8-4412-A9A8-80E85F3985A5}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FilePreviewCommon", "src\common\FilePreviewCommon\FilePreviewCommon.csproj", "{9EBAA524-0EDA-470B-95D4-39383285CBB2}"
EndProject
Global
@@ -1587,17 +1601,6 @@ Global
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x64.Build.0 = Release|x64
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.ActiveCfg = Release|x64
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.Build.0 = Release|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|ARM64.Build.0 = Debug|ARM64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|x64.ActiveCfg = Debug|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|x64.Build.0 = Debug|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|x86.ActiveCfg = Debug|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|ARM64.ActiveCfg = Release|ARM64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|ARM64.Build.0 = Release|ARM64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|x64.ActiveCfg = Release|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|x64.Build.0 = Release|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|x86.ActiveCfg = Release|x64
- {F44934A8-36F3-49B0-9465-3831BE041CDE}.Release|x86.Build.0 = Release|x64
{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|ARM64.ActiveCfg = Debug|ARM64
{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|ARM64.Build.0 = Debug|ARM64
{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|x64.ActiveCfg = Debug|x64
@@ -1669,18 +1672,6 @@ Global
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|x64.Build.0 = Release|x64
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|x86.ActiveCfg = Release|x64
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|x86.Build.0 = Release|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|ARM64.Build.0 = Debug|ARM64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|x64.ActiveCfg = Debug|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|x64.Build.0 = Debug|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|x86.ActiveCfg = Debug|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Debug|x86.Build.0 = Debug|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|ARM64.ActiveCfg = Release|ARM64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|ARM64.Build.0 = Release|ARM64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|x64.ActiveCfg = Release|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|x64.Build.0 = Release|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|x86.ActiveCfg = Release|x64
- {C5D46169-5334-48C3-8C28-644C72832E54}.Release|x86.Build.0 = Release|x64
{5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|ARM64.ActiveCfg = Debug|ARM64
{5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|ARM64.Build.0 = Debug|ARM64
{5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|x64.ActiveCfg = Debug|x64
@@ -2101,6 +2092,90 @@ Global
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x64.Build.0 = Release|x64
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x86.ActiveCfg = Release|x64
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x86.Build.0 = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.ActiveCfg = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.Build.0 = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x86.ActiveCfg = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x86.Build.0 = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.Build.0 = Release|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.ActiveCfg = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.Build.0 = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.ActiveCfg = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.Build.0 = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.ActiveCfg = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.Build.0 = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x86.ActiveCfg = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x86.Build.0 = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.Build.0 = Release|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.ActiveCfg = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.Build.0 = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.ActiveCfg = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.Build.0 = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.ActiveCfg = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.Build.0 = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.ActiveCfg = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.Build.0 = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.Build.0 = Release|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.ActiveCfg = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.Build.0 = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.ActiveCfg = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.Build.0 = Release|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.ActiveCfg = Debug|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.Build.0 = Debug|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x86.ActiveCfg = Debug|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x86.Build.0 = Debug|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.Build.0 = Release|ARM64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.ActiveCfg = Release|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.Build.0 = Release|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x86.ActiveCfg = Release|x64
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x86.Build.0 = Release|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.Build.0 = Debug|ARM64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x64.ActiveCfg = Debug|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x64.Build.0 = Debug|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x86.ActiveCfg = Debug|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x86.Build.0 = Debug|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|ARM64.ActiveCfg = Release|ARM64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|ARM64.Build.0 = Release|ARM64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x64.ActiveCfg = Release|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x64.Build.0 = Release|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x86.ActiveCfg = Release|x64
+ {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x86.Build.0 = Release|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x64.ActiveCfg = Debug|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x64.Build.0 = Debug|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x86.ActiveCfg = Debug|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x86.Build.0 = Debug|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|ARM64.Build.0 = Release|ARM64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x64.ActiveCfg = Release|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x64.Build.0 = Release|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x86.ActiveCfg = Release|x64
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x86.Build.0 = Release|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|ARM64.Build.0 = Debug|ARM64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x64.ActiveCfg = Debug|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x64.Build.0 = Debug|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x86.ActiveCfg = Debug|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x86.Build.0 = Debug|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|ARM64.ActiveCfg = Release|ARM64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|ARM64.Build.0 = Release|ARM64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x64.ActiveCfg = Release|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x64.Build.0 = Release|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x86.ActiveCfg = Release|x64
+ {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x86.Build.0 = Release|x64
{9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|ARM64.ActiveCfg = Debug|ARM64
{9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|ARM64.Build.0 = Debug|ARM64
{9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|x64.ActiveCfg = Debug|x64
@@ -2236,14 +2311,12 @@ Global
{F7C8C0F1-5431-4347-89D0-8E5354F93CF2} = {2F305555-C296-497E-AC20-5FA1B237996A}
{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC} = {2F305555-C296-497E-AC20-5FA1B237996A}
{04B193D7-3E21-46B8-A958-89B63A8A69DE} = {2F305555-C296-497E-AC20-5FA1B237996A}
- {F44934A8-36F3-49B0-9465-3831BE041CDE} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{FD464B4C-2F68-4D06-91E7-4208146C41F5} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{020A7474-3601-4160-A159-D7B70B77B15F} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{27718999-C175-450A-861C-89F911E16A88} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
- {C5D46169-5334-48C3-8C28-644C72832E54} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{93B72A06-C8BD-484F-A6F7-C9F280B150BF} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853} = {6C7F47CC-2151-44A3-A546-41C70025132C}
@@ -2285,6 +2358,15 @@ Global
{CA5518ED-0458-4B09-8F53-4122B9888655} = {2F305555-C296-497E-AC20-5FA1B237996A}
{D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D} = {2F305555-C296-497E-AC20-5FA1B237996A}
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA} = {2F305555-C296-497E-AC20-5FA1B237996A}
+ {8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {D9C5DE64-6849-4278-91AD-9660AECF2876} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
+ {FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B}
+ {9CE59ED5-7087-4353-88EB-788038A73CEC} = {1AFB6476-670D-4E80-A464-657E01DFF482}
+ {FD86C06A-FB54-4D5E-9831-1CDADF60D45F} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
+ {697C6AF9-0A48-49A9-866C-67DA12384015} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
+ {929C1324-22E8-4412-A9A8-80E85F3985A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{9EBAA524-0EDA-470B-95D4-39383285CBB2} = {1AFB6476-670D-4E80-A464-657E01DFF482}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
diff --git a/README.md b/README.md
index 737071f805..4ecd7e1d72 100644
--- a/README.md
+++ b/README.md
@@ -20,9 +20,10 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
| [Always on Top](https://aka.ms/PowerToysOverview_AoT) | [PowerToys Awake](https://aka.ms/PowerToysOverview_Awake) | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) |
| [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) | [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) |
| [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
-| [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
-| [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
-| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
+| [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) |
+| [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) |
+| [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) |
+| [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
## Installing and running Microsoft PowerToys
@@ -34,27 +35,36 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
### Via GitHub with EXE [Recommended]
-Go to [Microsoft PowerToys GitHub releases page][github-release-link], click on `Assets` at the bottom to show the files available in the release. Please use the appropriate the PowerToys installer that matches your machine's architecture. For most, it is `x64`.
+Go to [Microsoft PowerToys GitHub releases page][github-release-link], click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
- - **For x64 processors (most common):** [PowerToysSetup-0.66.0-x64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.66.0/PowerToysSetup-0.66.0-x64.exe)
- - **For ARM64 processors:** [PowerToysSetup-0.66.0-arm64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.66.0/PowerToysSetup-0.66.0-arm64.exe)
+ - **For x64 processors (most common) per-user installer:** [PowerToysUserSetup-0.69.1-x64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysUserSetup-0.69.1-x64.exe)
+ - **For x64 processors per-machine installer:** [PowerToysSetup-0.69.1-x64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysSetup-0.69.1-x64.exe)
+ - **For ARM64 processors per-user installer:** [PowerToysUserSetup-0.69.1-arm64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysUserSetup-0.69.1-arm64.exe)
+ - **For ARM64 processors per-machine installer:** [PowerToysSetup-0.69.1-arm64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysSetup-0.69.1-arm64.exe)
This is our preferred method.
### Via Microsoft Store
-Install from the [Microsoft Store's PowerToys page][microsoft-store-link]. You must be using the [new Microsoft Store](https://blogs.windows.com/windowsExperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/) which will be available for both Windows 11 and Windows 10.
+Install from the [Microsoft Store's PowerToys page][microsoft-store-link]. You must be using the [new Microsoft Store](https://blogs.windows.com/windowsExperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/) which is available for both Windows 11 and Windows 10.
-### Via WinGet (Preview)
-Download PowerToys from [WinGet][winget-link]. To install PowerToys, run the following command from the command line / PowerShell:
+### Via WinGet
+Download PowerToys from [WinGet][winget-link]. Updating PowerToys via winget will respect current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
+#### User scope installer [default]
```powershell
winget install Microsoft.PowerToys -s winget
```
+#### Machine-wide scope installer
+
+```powershell
+winget install --scope machine Microsoft.PowerToys -s winget
+```
+
### Other install methods
-There are [community driven install methods](./doc/unofficialInstallMethods.md) such as Chocolatey and Scoop. If these are your preferred install solutions, this will have the install instructions.
+There are [community driven install methods](./doc/unofficialInstallMethods.md) such as Chocolatey and Scoop. If these are your preferred install solutions, you can find the install instructions there.
## Contributing
@@ -72,32 +82,35 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
-### 0.66 - December 2022 Update
+### 0.69 - March 2023 Update
-In this release, we focused on stability and improvements.
+In this release, we focused on releasing new features, stability and improvements. Early notice for v0.70, we will be releasing it later in May 2023.
**Highlights**
-- PowerToy utilities now ship with self-contained .NET 7, meaning it's not necessary to install .NET as part of the installer and it's easier to keep up to date.
-- It's possible to pick which of the installed OCR languages is used by Text Extractor by selecting it in the right-click context menu.
-- Added a setting to sort the order of the accented characters by usage frequency in Quick Accent.
+- New utility: Registry Preview is a utility to visualize and edit Windows Registry files. Thanks [@randyrants](https://github.com/randyrants)!
+- Support per-user scope installation.
+- Awake: Quality-of-life improvements and introduced keeping system awake until expiration time and date. Thanks [@dend](https://github.com/dend)!
+- PowerToys Run: Fix crashing issue caused by thumbnail image loading.
### General
-- Reduced resource consumption caused by logging. A thread for each logger was being created even for disabled utilities.
-- The .NET 7 dependency is now shipped self-contained within the utilities, using deep links to reduce storage space usage.
+- New utility: Registry Preview. Thanks [@randyrants](https://github.com/randyrants)!
+- Fix issue causing folders to not be removed on uninstall.
+- Support per-user scope installation.
+ - Companies can control this using the new GPO.
+
+### Awake
+
+- Quality-of-life improvements and introduced keeping system awake until expiration time and date. Thanks [@dend](https://github.com/dend)!
### Color Picker
-- Fixed an issue where the custom color formats were not working when picking colors without using the editor.
-- Fixed a crash when using duplicated names for color formats.
-- Added two decimal formats, to distinguish between RGB and BGR.
-- Fixed color name localization, which was not working correctly on 0.65.
+- Fix issue sampling timing and grid issue causing Color Picker to sample the color of its own grid. Thanks [@IHorvalds](https://github.com/IHorvalds)!
### FancyZones
-- Fixed an editor crash caused by deleting a zone while trying to move it.
-- Reduce the time it takes the tooltip for layout shortcut setting to appear in the editor.
+- Fix window cycling on multiple monitors issue.
### File explorer add-ons
@@ -105,73 +118,80 @@ In this release, we focused on stability and improvements.
### File Locksmith
-- Fixed an issue causing File Locksmith to hang when looking for open handles in some machines.
+- Add context menu icon. Thanks [@htcfreek](https://github.com/htcfreek)!
-### Hosts File Editor
+### Mouse Utils
-- Added a warning when duplicated entries are detected. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
+- Mouse Jump - Simulate mouse input event on mouse jump in addition to cursor move.
+- Mouse Jump - Improve performance of screenshot generation. Thanks [@mikeclayton](https://github.com/mikeclayton)!
+
+### Paste as Plain Text
+
+- Support Ctrl+V as activation shortcut. (This was a hotfix for 0.67)
+- Repress modifier keys after plain paste. (This was a hotfix for 0.67) Thanks [@UnderKoen](https://github.com/UnderKoen)!
+- Set default shortcut to Ctrl+Win+Alt+V. (This was a hotfix for 0.67)
+- Update icons. Thanks [@niels9001](https://github.com/niels9001)!
+
+### PowerRename
+
+- Show PowerRename in directory background context menu.
+- Fix the crash on clicking Select/UnselectAll checkbox while showing only files to be renamed.
+- Improve performance on populating Renamed items when many items are being renamed.
### PowerToys Run
-- Support drag and dropping for file results. Thanks [@daniel-richter](https://github.com/daniel-richter)!
+- Add setting to disable thumbnails generation for files. (This was a hotfix for 0.67)
+- Calculator plugin - handle implied multiplication expressions. Thanks [@jjavierdguezas](https://github.com/jjavierdguezas)!
+- Fix Calculator plugin unit tests to respect decimal separator locale. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
+- Fix crashing caused by thumbnail image loading.
+- Date & Time plugin - Add filename-compatible date & time format. Thanks [@Picazsoo](https://github.com/Picazsoo)!
+- Improved the error message shown on plugin loading error. Thanks [@htcfreek](https://github.com/htcfreek)!
### Quick Accent
-- Added support for dark theme. Thanks [@niels9001](https://github.com/niels9001)!
-- Increased default input delay to improve out of the box experience.
-- Fixed a bug causing the first character to not be selected when opening the overlay. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
-- Fixed the positioning of the overlay when showing near the horizontal edges of the screen.
-- Added additional Pinyin characters. Thanks [@char-46](https://github.com/char-46)!
-- Added Macedonian characters. Thanks [@ad-mca-mk](https://github.com/ad-mca-mk)!
-- Added a setting to sort characters by usage frequency.
-- Added a setting to always start selection in the first character, even when using the arrow keys as the activation method.
+- Fix existing and add missing Hebrew and Pinyin characters. Thanks [@stevenlele](https://github.com/stevenlele)!
-### Settings
+### Registry Preview
-- Fixed an error that hid the option to keep the display on when using the "Indefinitely Awake" mode.
-- Fixed an accessibility issue causing the navigation bar to not work with narrator in scan mode.
-- Fixed an accessibility issue where the name for the shortcut control was not being read correctly.
-- Tweaked the Color Picker custom color format UI. Thanks [@niels9001](https://github.com/niels9001)!
-- Improved the shortcut control visibility and accessibility. Thanks [@niels9001](https://github.com/niels9001)!
-- Fixed an issue causing the Settings to not be saved correctly on scenarios where the admin user would be different then the user running PowerToys.
-- Added a setting to pick which language should be used by default when using Text Extractor.
-
-### Text Extractor
-
-- Improve behavior for CJK languages by not adding spaces for some characters that don't need them. Thanks [@AO2233](https://github.com/AO2233)!
-- OCR language can now be picked in the right-click context menu.
+- Added a new utility: Registry Preview.
+- Thanks [@htcfreek](https://github.com/htcfreek)! for the help shipping this utility!
+- Thanks [@niels9001](https://github.com/niels9001) for the help on the UI!
### Video Conference Mute
-- Reduced resource consumption by not starting the File Watchers when the utility is disabled.
+- Add toolbar DPI scaling support.
+- Fix selecting overlay image when Settings app is running elevated.
+- Add push-to-talk (and push-to-reverse) feature. Thanks [@pajawojciech](https://github.com/pajawojciech)!
+
+### Settings
+
+- Fix Experiment bitmap icon rendering on theme change and bump CommunityToolkit.Labs.WinUI.SettingsControls package version. Thanks [@niels9001](https://github.com/niels9001)!
+- Video Conference Mute page improvements. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
+- Add warning that PowerToys Run might get no focus if "Use centralized keyboard hook" settings is enabled. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
+- Fix ShortcutControl issues related to keyboard input focus, theme change and missing error badge when invalid key is pressed. Thanks [@htcfreek](https://github.com/htcfreek)!
+- Add warning when Ctrl+V and Ctrl+Shift+V is used as an activation shortcut for Paste as Plain Text. Thanks [@htcfreek](https://github.com/htcfreek)!
### Documentation
-- Updated the development setup documentation.
-- Improved the Markdown documentation lists numbering in many docs. Thanks [@sanidhyas3s](https://github.com/sanidhyas3s)!
+- Update CONTRIBUTING.md with information about localization issues. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
+- Remove localization from URLs. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
+- Add dev docs for tools. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
### Development
-- Turned on C++ code analysis and incrementally fixing warnings.
-- C++ code analysis no longer runs on release CI to speed up building release candidates. It still runs on GitHub CI and when building locally to maintain code quality.
-- Cleaned up "to-do" comments referring to disposing memory on C#. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
-- Added a fabric bot rule for localization issues.
-- Fixed a CI build error after a .NET tools update.
-- Update the Windows App SDK dependency version to 1.2.
-- When building for arm64, the arm64 build tools are now preferred when building on an arm64 device. Thanks [@snickler](https://github.com/snickler)!
-- Updated the C# test framework and removed unused Newtonsoft.Json package references.
-- Updated StyleCop and fixed/enabled more warnings. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
-- Fixed a language typo in the code. Thanks [@eltociear](https://github.com/eltociear)!
-- Improved code quality around some silent crashes that were being reported to Microsoft servers.
-- Moved the GPO asset files to source instead of docs in the repo.
-- Upgraded the unit test NuGet packages.
+- Ignore spellcheck for MouseJumpUI/MainForm.resx file. (This was a hotfix for 0.67)
+- Optimize versionAndSignCheck.ps1 script. Thanks [@snickler](https://github.com/snickler)!
+- Upgraded NetAnalyzers to 7.0.1. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
+- Move all DLL imports in Settings project to NativeMethods.cs file.
+- Fix FancyZones tools build issues. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
+- Centralize Logger used in C# projects. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
+- Add missing project references. Thanks [@ACGNnsj](https://github.com/ACGNnsj)!
-#### What is being planned for version 0.67
+#### What is being planned for version 0.70
-For [v0.67][github-next-release-work], we'll work on below:
+For [v0.70][github-next-release-work], we'll work on below:
-- Allow installing without UAC.
-- Add a flyout menu to the system tray icon for quick access.
+- New utility: [PowerToys Peek](https://github.com/microsoft/PowerToys/issues/80)
- Stability / bug fixes
## PowerToys Community
@@ -199,5 +219,5 @@ The application logs basic telemetry. Our Telemetry Data page (Coming Soon) has
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
-[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F40
-[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F39
+[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F43
+[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F42
diff --git a/doc/devdocs/disk-usage-footprint.md b/doc/devdocs/disk-usage-footprint.md
new file mode 100644
index 0000000000..08de4bd7bd
--- /dev/null
+++ b/doc/devdocs/disk-usage-footprint.md
@@ -0,0 +1,82 @@
+# PowerToys disk usage footprint overview
+
+As of the v0.66 of PowerToys, core runtime dlls are being shipped self-contained as a part of PowerToys. During the installation process, hard-links are being created for every module that needs any of these shared libraries.
+
+## Why do this work?
+
+Our main motivations for doing are the following:
+
+1. Be able to install PowerToys without UAC elevation
+2. PowerToys has a reduced disk space when components are shared.
+3. Reduce additional downloads for dependencies
+
+## Current self-contained runtimes
+
+These dll's are installed in `/dll/- ` folder structure.
+
+- [Windows Application SDK runtime](https://learn.microsoft.com/windows/apps/windows-app-sdk/downloads)
+- [.NET Desktop Runtime 7](https://dotnet.microsoft.com/download/dotnet/7.0)
+- [Microsoft Visual C++ Runtime](https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist?view=msvc-170)
+
+## So why does PowerToys have a larger footprint now?
+
+Before the hard-link work was done, each of these runtimes had to be installed, so there were more items being installed outside just the PowerToys install directory. This space would not have been accounted.
+
+File Explorer treats hard-links the same as "original"/regular files/directories (https://learn.microsoft.com/troubleshoot/windows-server/backup-and-storage/disk-space-problems-on-ntfs-volumes#other-ntfs-features-that-may-cause-file-allocation-confusion), not as links. This results in File Explorer reporting size of PowerToys installation directory bigger than it is (more than 2GB).
+
+## How much space is actually being used
+
+As of v0.66 of PowerToys, the installed footprint is ~660MB.
+
+When we were prototyping and validating, here was our running table of results and why we took the route we did.
+
+| Moment | Installer size | App size | Installation dir size | Real size | Deps downloaded and installed during PT install | Total (installer size + real size + deps downloaded and installed during PT install) |
+|---|---|---|---|---|---|---|
+| v0.62.0.1
no deps self-contained | 125 MB | 817 MB | 529 MB | 534 MB | 418 MB | 1,077 MB |
+| v0.63.0
WAS and VCRedist | 83 MB | 587 MB | 567 MB | 396 MB | 394 MB | 873 MB |
+| v0.63.0
WAS1.2preview and VCRedist| 80 MB | 574 MB | 539 MB | 385 MB | 394 MB | 859 MB |
+| Full Test
WAS, VCRedist, .NET | 149 MB | 705 MB | 1,760 MB | 557 MB | 0 MB | 706 MB |
+
+## Our process to verify current install footprint
+
+We created a quick virtual machine. We chose to use our fresh Windows 10 test virtual machines here.
+
+### Empty disk details
+
+
+
+### Install PowerToys to empty disk
+
+
+
+### PowerToys installation directory size shown by File Explorer
+
+As mentioned above, File Explorer shows size of PowerToys installation dir as every hard-link is a regular file for itself
+
+
+
+### PowerToys size shown by App->Installed apps
+
+
+
+### Disk usage with PowerToys installed
+
+Real disk usage of PowerToys is shown by inspecting disk usage after installing PowerToys. Used space is now 695MB, comparing to ~35MB used space for empty disk gives us the size of ~660MB for PowerToys installation dir.
+
+
+
+### PowerShell command calculating size of non-hardlinks files
+
+Size of regular files (non-hard-links) and hard-links can also be obtained by running following PowerShell command in PowerToys installation dir:
+
+```
+Regular files:
+ls -Recurse -File -force -ErrorAction SilentlyContinue | ? LinkType -ne HardLink | Measure-Object -Property Length -Sum
+
+Hard-links
+ls -Recurse -File -force -ErrorAction SilentlyContinue | ? LinkType -e HardLink | Measure-Object -Property Length -Sum
+```
+
+Running these commands for PowerToys v0.66 shows that size of regular files is way less than size of hard-links pointing to some of those regular files because PowerShell (same as File Explorer) also takes the size of hard-links as of regular files.
+
+
diff --git a/doc/devdocs/logging.md b/doc/devdocs/logging.md
index 57f2d13844..f98a03820a 100644
--- a/doc/devdocs/logging.md
+++ b/doc/devdocs/logging.md
@@ -1,9 +1,61 @@
-# How to use
+# Logging
-We use the awesome [spdlog](https://github.com/gabime/spdlog) library for logging as a git submodule under the `deps` directory. To use it in your project, just include [spdlog.props](../../deps/spdlog.props) in a .vcxproj like this:
+Logging plays an important part in determining bugs in our code. It provides context for the developers about where and when errors occur.
+
+## Where are the logs saved
+
+* Most of the logs are saved under `%LOCALAPPDATA%/Microsoft/PowerToys`.
+* For low-privilege processes (like preview handlers) the logs are saved under `%USERPROFILE%/AppData/LocalLow/Microsoft/PowerToys`.
+
+Logs are normally in a subfolder with the module name as title.
+
+The [BugReportTool](/tools/BugReportTool) will take logs from both locations when executed.
+
+## Using a logger in a project
+
+### Spdlog
+
+In C++ projects we use the awesome [spdlog](https://github.com/gabime/spdlog) library for logging as a git submodule under the `deps` directory. To use it in your project, just include [spdlog.props](/deps/spdlog.props) in a .vcxproj like this:
```xml
```
It'll add the required include dirs and link the library binary itself.
+### PowerToys Logger in ManagedCommon
+
+For C# projects there is a static logger class in Managed Common called `Logger`.
+
+To use it, add a project reference to `ManagedCommon` and add the following line of code to all the files using the logger:
+
+```Csharp
+using ManagedCommon;
+```
+
+In the `Main` function (or a function with a similar meaning (like `App` in a `App.xaml.cs` file)) you have to call `InitializeLogger` and specify the location where the logs will be saved (always use a path scheme similar to this example):
+
+```Csharp
+Logger.InitializeLogger("\\FancyZones\\Editor\\Logs");
+```
+
+For a low-privilege process you have to set the optional second parameter to `true`:
+
+```Csharp
+Logger.InitializeLogger("\\FileExplorer\\Monaco\\Logs", true);
+```
+
+The `Logger` class contains the following logging functions:
+
+```Csharp
+// Logs an error that the utility encountered
+Logger.LogError(string message);
+Logger.LogError(string message, Exception ex);
+// Logs an error that isn't that grave
+Logger.LogWarning(string message);
+// Logs what the app is doing at the moment
+Logger.LogInfo(string message);
+// Like LogInfo just with infos important for debugging
+Logger.LogDebug(string message);
+// Logs the current state of the utility.
+Logger.LogTrace();
+```
diff --git a/doc/devdocs/modules/launcher/plugins/calculator.md b/doc/devdocs/modules/launcher/plugins/calculator.md
index 79ffe208a8..d9ac8e1e56 100644
--- a/doc/devdocs/modules/launcher/plugins/calculator.md
+++ b/doc/devdocs/modules/launcher/plugins/calculator.md
@@ -21,7 +21,12 @@ The Calculator plugin as the name suggests is used to perform calculations on th
### [`CalculateHelper`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs)
- The [`CalculateHelper.cs`](src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs) class checks to see if the user entered query is a valid input to the calculator and only if the input is valid does it perform the operation.
-- It does so by matching the user query to a valid regex.
+ - It does so by matching the user query to a valid regex.
+- This class also handles some human multiplication expression like `2(1+2)` and `(2+3)(3+4)` in order to be computed by `Mages` lib.
+ - It does so by matching some regex and inserting `'*'` where appropriate, e.g: `2(1+2) -> 2 * (1+2)`
+ - It takes into account the combination of numbers (`num`), constants (`const`), functions (`func`) and expressions in parentheses (`(exp)`).
+ - The blank spaces between them are also considered.
+ - Some combinations were not handled as they are not common such as `'const num'` or `'func const'`
### [`CalculateEngine`](src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs)
- The main computation is done in the [`CalculateEngine.cs`](src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs) file using the `Mages` library.
diff --git a/doc/devdocs/modules/launcher/plugins/program.md b/doc/devdocs/modules/launcher/plugins/program.md
index cc370258ec..1c3d86ba07 100644
--- a/doc/devdocs/modules/launcher/plugins/program.md
+++ b/doc/devdocs/modules/launcher/plugins/program.md
@@ -41,3 +41,7 @@ There are broadly two different categories of applications:
### Additional Notes
- Arguments can be provided to the program plugin by entering them after `--` (a double dash).
+- The localization is done using the `Localization Helper`from `Wox.Plugin.Common` hosted at runtime in a variable of plugin's main class.
+- The `Run commands` differ in two points from the normal `Win32Programs`:
+ - The result title contains the executable type.
+ - The file types `.cpl` and `.msc` are supported too.
diff --git a/doc/devdocs/modules/launcher/plugins/timeZone.md b/doc/devdocs/modules/launcher/plugins/timeZone.md
deleted file mode 100644
index 49710cb947..0000000000
--- a/doc/devdocs/modules/launcher/plugins/timeZone.md
+++ /dev/null
@@ -1,141 +0,0 @@
-# Time Zone Plugin
-
-The Time Zone plugin allows users to search a time zone.
-
-## Special functions (differ from the regular functions)
-
-* Search for a country, like Kamchatka, Prince Edward Island, France
-* Search for a shortcuts, like WEST, UTC, PST
-* Search for a offset, like -12:00, -7, 5, 9:30
-* Search for a military time zone name (must activate in plugin settings)
-
-## How to add a new time zone or change one
-
-All time zones are located in `TimeZone.json` in root folder of the project.
-The `TimeZone.json` use a JSON schema file that make it easier to edit it.
-
-| Key | Optional | Value type |
-| ------------------- | -------- | ----------------- |
-| `Offset` | **No** | String |
-| `Name` | Yes | String |
-| `MilitaryName` | Yes | String |
-| `Shortcut` | Yes | String |
-| `TimeNamesStandard` | Yes | List with strings |
-| `TimeNamesDaylight` | Yes | List with strings |
-| `ShortcutsStandard` | Yes | List with strings |
-| `ShortcutsDaylight` | Yes | List with strings |
-| `CountriesStandard` | Yes | List with strings |
-| `CountriesDaylight` | Yes | List with strings |
-
-A minimum entry for the `TimeZone.json` looks like:
-
-```json
- {
- "Offset": "11:55",
- "Name": "My crazy time zone",
- }
-```
-
-A full entry for the `TimeZone.json` looks like:
-
-```json
- {
- "Offset": "11:55",
- "Name": "My crazy time zone",
- "Shortcut" : "MYTZ",
- "MilitaryName" : "Order Time Zone",
- "TimeNamesStandard": [
- "My crazy standard time"
- ],
- "ShortcutsStandard": [
- "MCST"
- ],
- "TimeNamesDaylight": [
- "My crazy daylight time"
- ],
- "ShortcutsDaylight": [
- "MCDT"
- ],
- "CountriesStandard": [
- "Crazy Land East"
- ],
- "CountriesDaylight": [
- "Crazy Land West"
- ]
- }
-```
-
-### Remarks
-
-* At minimum one of the optional value should be filled.
-
-## Scores
-
-* Scores are not used
-
-## Important for developers
-
-### General
-
-* The assembly name is cached into `_assemblyName` (to avoid to many calls of `Assembly.GetExecutingAssembly()`)
-
-## Microsoft.PowerToys.Run.Plugin.TimeZone project
-
-### Important plugin values (meta-data)
-
-| Name | Value |
-| --------------- | ---------------------------------------------------- |
-| ActionKeyword | `&` |
-| ExecuteFileName | `Microsoft.PowerToys.Run.Plugin.TimeZone.dll` |
-| ID | `BADD1B06EF0A4B61AD95395F24241D69` |
-
-### Interfaces used by this plugin
-
-The plugin use only these interfaces (all inside the `Main.cs`):
-
-* `Wox.Plugin.IPlugin`
-* `Wox.Plugin.IContextMenu`
-* `Wox.Plugin.IPluginI18n`
-* `Wox.Plugin.ISettingProvider`
-* `IDisposable`
-
-### Program files
-
-| File | Content |
-| -------------------------------------- | ----------------------------------------------------------------------- |
-| `Classes\TimeZoneProperties.cs` | A class that represent one time zone |
-| `Classes\TimeZones.cs` | A wrapper class that only contains a list with time zones (see 1) |
-| `Classes\TimeZoneSettings.cs` | A class that contains all settings for the Time Zone plugin |
-| `Extensions\StringBuilderExtension.cs` | Extension methods for `StringBuilder` Objects |
-| `Helper\ContextMenuHelper.cs` | All functions to build the context menu (for each result entry) |
-| `Helper\JsonHelper.cs` | All functions to load the time zones from a JSON file |
-| `Helper\ResultHelper.cs` | All functions to convert internal results into WOX results |
-| `Helper\TranslationHelper.cs` | All functions to translate the result in the surface language |
-| `Images\timeZone.dark.png` | Symbol for the results for the dark theme |
-| `Images\timeZone.light.png` | Symbol for the results for the light theme |
-| `Properties\Resources.Designer.resx` | File that contain all translatable keys |
-| `Properties\Resources.resx` | File that contain all translatable strings in the neutral language |
-| `Main.cs` | Main class, the only place that implement the WOX interfaces |
-| `plugin.json` | All meta-data for this plugin |
-| `timezones.json` | File that contains all time zone information |
-| `timeZones.schema.json` | JSON schema for `timezones.json` |
-
-1. We need this extra wrapper class to make it possible that the JSON file can have and use a JSON schema file.
-Because the JSON file must have a object as root type, instead of a array.
-
-### Important project values (*.csproj)
-
-| Name | Value |
-| --------------- | ------------------------------------------------------------- |
-| TargetFramework | `net6.0-windows` |
-| Platforms | `x64` |
-| Output | `..\..\..\..\..\x64\Debug\modules\launcher\Plugins\TimeZone\` |
-| RootNamespace | `Microsoft.PowerToys.Run.Plugin.TimeZone` |
-| AssemblyName | `Microsoft.PowerToys.Run.Plugin.TimeZone` |
-
-### Project dependencies
-
-#### Projects
-
-* `Wox.Infrastructure`
-* `Wox.Plugin`
diff --git a/doc/devdocs/modules/launcher/plugins/windowssettings.md b/doc/devdocs/modules/launcher/plugins/windowssettings.md
index b057374472..9141afed97 100644
--- a/doc/devdocs/modules/launcher/plugins/windowssettings.md
+++ b/doc/devdocs/modules/launcher/plugins/windowssettings.md
@@ -62,6 +62,7 @@ A full entry for the `WindowsSettings.json` looks like:
* The strings for `Name`, `AltNames`, `Areas`, `Type` and `Note` must not contain whitespace(s) or special characters (#, €, $, etc.)
* The strings for `Name`, `AltNames`, `Areas`, `Type` and `Note` are used as ids for the resource file under `Properties\Resources.resx`
* When you add new strings make sure you have added all translations for it.
+* If a result has `mmc.exe` as command and the note property is filled, the note is shown in the sub title too. (This is for special MMC results where we don't have a .msc file.)
## Scores
diff --git a/doc/devdocs/readme.md b/doc/devdocs/readme.md
index 88b0867bd7..7c2a12061a 100644
--- a/doc/devdocs/readme.md
+++ b/doc/devdocs/readme.md
@@ -40,7 +40,7 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and you
1. Windows 10 April 2018 Update (version 1803) or newer
1. Visual Studio Community/Professional/Enterprise 2022 17.4 or newer
1. Git clone PowerToys repository
-1. Open started the `PowerToys.sln`
+1. Open the `PowerToys.sln` file.
1. If you see a dialog that says `install extra components` in the solution explorer pane, click `install`
### Get Submodules to compile
@@ -73,8 +73,8 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done
### Prerequisites for building the MSI installer
1. Install the [WiX Toolset Visual Studio 2022 Extension](https://marketplace.visualstudio.com/items?itemName=WixToolset.WixToolsetVisualStudio2022Extension).
-1. Install the [WiX Toolset build tools](https://wixtoolset.org/releases/v3-14-0-6526/). The links to the binaries are not working, so we've created a [fork here](https://github.com/JaneaSystems/wix3/releases/tag/wix3-3.14.0.6526) where the WiX Toolset can be downloaded from.
-1. Download [WiX binaries](https://github.com/JaneaSystems/wix3/releases/download/wix3-3.14.0.6526/wix314-binaries.zip) and extract `wix.targets` to `C:\Program Files (x86)\WiX Toolset v3.14`.
+1. Install the [WiX Toolset build tools](https://wixtoolset.org/docs/v3/releases/v3-14-0-6526/). (installer [direct link](https://wixtoolset.org/downloads/v3.14.0.6526/wix314.exe))
+1. Download [WiX binaries](https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip) and extract `wix.targets` to `C:\Program Files (x86)\WiX Toolset v3.14`.
### Locally building the installer prerequisite projects all at once from the command-line
@@ -137,7 +137,7 @@ To run and debug PowerToys from Visual Studio when the user is a member of the A
## How to create new PowerToys
See the instructions on [how to install the PowerToys Module project template](/tools/project_template).
-Specifications for the [PowerToys settings API](/doc/devdocs/settings.md).
+Specifications for the [PowerToys settings API](settingsv2/readme.md).
## Implementation details
diff --git a/doc/devdocs/tools/bug-report-tool.md b/doc/devdocs/tools/bug-report-tool.md
new file mode 100644
index 0000000000..f73bdf3fc3
--- /dev/null
+++ b/doc/devdocs/tools/bug-report-tool.md
@@ -0,0 +1,31 @@
+# [Bug report tool](/tools/BugReportTool/)
+
+This tool is used to collect logs and system information for bug reports. The bug report is then saved as a zip file on the desktop.
+
+## Launching
+
+It can launch from the PowerToys tray icon by clicking "Report Bug", by clicking the bug report icon in the PowerToys flyout or by running the executable directly.
+
+## Included files
+
+The bug report includes the following files:
+
+* Settings files of the modules.
+* Logs of the modules and the runner.
+* Update log files.
+* `compatibility-tab-info.txt` - Information about [compatibility settings](https://support.microsoft.com/windows/make-older-apps-or-programs-compatible-with-windows-783d6dd7-b439-bdb0-0490-54eea0f45938) set for certain PowerToys executables both in the user and system scope.
+* `context-menu-packages.txt` - Information about the packages that are registered for the new Windows 11 context menu.
+* `dotnet-installation-info.txt` - Information about the installed .NET versions.
+* `EventViewer-*.xml` - These files contain event logs from the Windows Event Viewer for the executable specified in the file name.
+* `gpo-configuration-info.txt` - Information about the configured [GPO](/doc/gpo/README.md).
+* `installationFolderStructure.txt` - Information about the folder structure of the installation. All lines with files have the following structure: `FileName Version MD5Hash`.
+* `last_version_run.json` - Information about the last version of PowerToys that was run.
+* `log_settings.json` - Information about the log level settings.
+* `monitor-report-info.txt` - Information about the monitors connected to the system. This file is created by the [monitor info report tool](/doc/devdocs/tools/monitor-info-report.md).
+* `oobe_settings.json` - Information about the OOBE settings.
+* `registry-report-info.txt` - Information about the registry keys that are used by PowerToys.
+* `settings_placement.json` - Information about the placement of the settings window.
+* `settings-telemetry.json` - Information about the last time telemetry data was sent.
+* `UpdateState.json` - Information about the last update check and the current status of the update download.
+* `windows-settings.txt` - Information about the Windows language settings.
+* `windows-version.txt` - Information about the Windows version.
diff --git a/doc/devdocs/tools/build-tools.md b/doc/devdocs/tools/build-tools.md
new file mode 100644
index 0000000000..dfa4e251b2
--- /dev/null
+++ b/doc/devdocs/tools/build-tools.md
@@ -0,0 +1,31 @@
+# [Build tools](/tools/build/)
+
+These build tools help building PowerToys projects.
+
+## [build-essentials.ps1](/tools/build/build-essentials.ps1)
+
+A script that builds certain specified PowerToys projects. You can edit the `$ProjectsToBuild` variable to specify which projects to build.
+
+## [convert-resx-to-rc.ps1](/tools/build/convert-resx-to-rc.ps1)
+
+This script converts a .resx file to a .rc file, so it can be used in a C++ project. More information on localization can be found in the [localization guide](/doc/devdocs/localization.md).
+
+## [convert-stringtable-to-resx.ps1](/tools/build/convert-stringtable-to-resx.ps1)
+
+This script converts a stringtable to a .resx file, so it can be used in a C# project. More information about this script can be found in the [localization guide](/doc/devdocs/localization.md).
+
+## [move-and-rename-resx.ps1](/tools/build/move-and-rename-resx.ps1)
+
+This script is used by the pipeline to move the .resx files to the correct location, so that they can be localized into different languages.
+
+## [move-uwp-resw.ps1](/tools/build/move-uwp-resw.ps1)
+
+This script is used by the pipeline to move the .resw files to the correct location, so that they can be localized into different languages.
+
+## [versionSetting.ps1](/tools/build/versionSetting.ps1)
+
+Sets `version.props` file with the version number.
+
+## [video_conference_make_cab.ps1](/tools/build/video_conference_make_cab.ps1)
+
+This script creates a cab file for the Video Conference Mute driver.
diff --git a/doc/devdocs/tools/clean-up-tool.md b/doc/devdocs/tools/clean-up-tool.md
new file mode 100644
index 0000000000..f03eacdd32
--- /dev/null
+++ b/doc/devdocs/tools/clean-up-tool.md
@@ -0,0 +1,5 @@
+# [CleanUp_tool](/tools/CleanUp_tool/) and [CleanUp_tool_powershell_script](/tools/CleanUp_tool_powershell_script/CleanUp_tool.ps1)
+
+This tool, respective this powershell script, is used to clean up the PowerToys installation. It cleans the `AppData` folder and the registry.
+
+This tool is currently very outdated and just cleans up the registry keys of some few modules.
diff --git a/doc/devdocs/tools/fancyzone-hit-test.md b/doc/devdocs/tools/fancyzone-hit-test.md
new file mode 100644
index 0000000000..b49207faa0
--- /dev/null
+++ b/doc/devdocs/tools/fancyzone-hit-test.md
@@ -0,0 +1,5 @@
+# [FancyZone hit test tool](/tools/FancyZone_HitTest/)
+
+
+
+This tool tests the FancyZones layout selection logic. It displays a window with 5 zones. By hovering the mouse over the zones, the zone under the mouse cursor is highlighted. The sidebar shows different metrics that are used to determine which zone is under the mouse cursor.
diff --git a/tools/FancyZones_DrawLayoutTest/README.md b/doc/devdocs/tools/fancyzones-draw-layout-test.md
similarity index 86%
rename from tools/FancyZones_DrawLayoutTest/README.md
rename to doc/devdocs/tools/fancyzones-draw-layout-test.md
index 652124f7c7..9f15a3a2ad 100644
--- a/tools/FancyZones_DrawLayoutTest/README.md
+++ b/doc/devdocs/tools/fancyzones-draw-layout-test.md
@@ -1,7 +1,7 @@
-## Testing tool for drawing zone layout
+# [FancyZones_DrawLayoutTest](/tools/FancyZones_DrawLayoutTest/)
This test tool is created in order to debug issues related to the drawing of zone layout on screen.
Currently, only column layout is supported with modifiable number of zones. Pressing **w** key toggles zone appearance on primary screen (multi monitor support not yet in place). Pressing **q** key exits application.
-Application is DPI unaware which means that application does not scale for DPI changes and it always assumes to have a scale factor of 100% (96 DPI). Scaling will be automatically performed by the system.
\ No newline at end of file
+Application is DPI unaware which means that application does not scale for DPI changes and it always assumes to have a scale factor of 100% (96 DPI). Scaling will be automatically performed by the system.
diff --git a/doc/devdocs/tools/fancyzones-zonable-tester.md b/doc/devdocs/tools/fancyzones-zonable-tester.md
new file mode 100644
index 0000000000..0b552f4636
--- /dev/null
+++ b/doc/devdocs/tools/fancyzones-zonable-tester.md
@@ -0,0 +1,13 @@
+# [FancyZones_zonable_tester](/tools/FancyZones_zonable_tester/)
+
+
+
+This command line application tests if the window where the mouse cursor is located is zonable. It also adds additional information about the window to the console output:
+
+* The HWND (window handle) of the window
+* The process ID of the window
+* The HWND of the window in the foreground
+* The style of the window
+* The exStyle of the window
+* The window class
+* The path of the process that created the window
diff --git a/doc/devdocs/tools.md b/doc/devdocs/tools/monitor-info-report.md
similarity index 89%
rename from doc/devdocs/tools.md
rename to doc/devdocs/tools/monitor-info-report.md
index 2e14440c97..489f109a0e 100644
--- a/doc/devdocs/tools.md
+++ b/doc/devdocs/tools/monitor-info-report.md
@@ -1,10 +1,8 @@
-# Tools
-
-## [Monitor info report](tools\monitor_info_report)
+# [Monitor info report tool](/tools/MonitorReportTool)
A small diagnostic tool which helps identifying WinAPI bugs related to the physical monitor detection. When launched, it creates a log file like this:
-```
+```text
GetSystemMetrics = 2
GetMonitorInfo OK
EnumDisplayDevices OK:
@@ -20,4 +18,5 @@ EnumDisplayDevices OK:
DeviceString = Generic PnP Monitor
EnumDisplayMonitors OK
```
-and also duplicates the info to `stdout`.
\ No newline at end of file
+
+and also duplicates the info to `stdout`.
diff --git a/doc/devdocs/tools/readme.md b/doc/devdocs/tools/readme.md
new file mode 100644
index 0000000000..8794b77e3e
--- /dev/null
+++ b/doc/devdocs/tools/readme.md
@@ -0,0 +1,21 @@
+# PowerToys tools
+
+Tools in PowerToys are standalone apps and scripts that run outside of the PowerToys runner. They help developers and users to debug and test PowerToys features.
+
+The source code of the tools can be found in the [tools folder](/tools). The compiled tools are saved under `{PowerToysInstallPath}\tools`.
+
+## Overview of the tools
+
+Following tools are currently available:
+
+* [BugReportTool](bug-report-tool.md) - A tool to collect logs and system information for bug reports.
+* [Build tools](build-tools.md) - A set of scripts that help building PowerToys.
+* [Clean up tool](clean-up-tool.md) - A tool to clean up the PowerToys installation.
+* [FancyZones hit test](fancyzone-hit-test.md) - A tool to test FancyZones layout selection logic.
+* [FancyZones draw layout test](fancyzones-draw-layout-test.md) - A tool to test FancyZones layout drawing logic.
+* [FancyZones zonable tester](fancyzones-zonable-tester.md) - A tool to test if a window is zonable.
+* [Monitor info report](monitor-info-report.md) - A small diagnostic tool which helps identifying WinAPI bugs related to the physical monitor detection.
+* [project template](/tools/project_template/README.md) - A Visual Studio project template for a new PowerToys project.
+* [StylesReportTool](styles-report-tool.md) - A tool to collect information about an open window.
+* [Verification scripts](verification-scripts.md) - A set of scripts that help verifying the PowerToys installation.
+* [WebcamReportTool](webcam-report-tool.md) - A tool to collect information about the connected webcams.
diff --git a/doc/devdocs/tools/styles-report-tool.md b/doc/devdocs/tools/styles-report-tool.md
new file mode 100644
index 0000000000..bb31c9c98d
--- /dev/null
+++ b/doc/devdocs/tools/styles-report-tool.md
@@ -0,0 +1,12 @@
+# [Styles Report Tool](/tools/StylesReportTool/)
+
+The Styles Report Tool is a tool to collect information about an open window. Run the tool, bring the window to the foreground and press Ctrl+Alt+S. The tool will create a file on your desktop called `window_styles.txt` with the information about the window.
+
+## Collected information
+
+* Process name
+* Window class
+* Window style parameters
+* Window exStyle parameters
+* DWM attributes
+* Infos about the Virtual Desktop the window is on
diff --git a/doc/devdocs/tools/verification-scripts.md b/doc/devdocs/tools/verification-scripts.md
new file mode 100644
index 0000000000..cff58f478f
--- /dev/null
+++ b/doc/devdocs/tools/verification-scripts.md
@@ -0,0 +1,25 @@
+# [Verification Scripts](/tools/Verification%20scripts/)
+
+This folder contains powershell scripts that help verifying the PowerToys installation.
+
+## [Check preview handler registration](/tools/Verification%20scripts/Check%20preview%20handler%20registration.ps1)
+
+This script checks the preview handler registration for the following file types:
+
+* .markdown
+* .mdtext
+* .mdtxt
+* .mdown
+* .mkdn
+* .mdwn
+* .mkd
+* .md
+* .svg
+* .svgz
+* .pdf
+* .gcode
+* .stl
+* .txt
+* .ini
+
+The tool shows the user handler and the machine handler for each file type and displays the App GUID of the corresponding handler.
diff --git a/doc/devdocs/tools/webcam-report-tool.md b/doc/devdocs/tools/webcam-report-tool.md
new file mode 100644
index 0000000000..efa6d47da3
--- /dev/null
+++ b/doc/devdocs/tools/webcam-report-tool.md
@@ -0,0 +1,6 @@
+# [WebcamReportTool](/tools/WebcamReportTool/)
+
+This command line application generates a report about the connected webcams on the desktop called "WebcamReport.txt". The report contains the following information about every webcam:
+
+* Name
+* Supported formats
diff --git a/doc/gpo/README.md b/doc/gpo/README.md
index 482c3f6271..351ed5a376 100644
--- a/doc/gpo/README.md
+++ b/doc/gpo/README.md
@@ -31,3 +31,52 @@ If you enable this setting, the utility will be always enabled and the user won'
If you disable this setting, the utility will be always disabled and the user won't be able to enable it.
If you don't configure this setting, users are able to disable or enable the utility.
+
+### Allow experimentation
+
+This policy configures whether PowerToys experimentation is allowed. With experimentation allowed the user sees the new features being experimented if it gets selected as part of the test group. (Experimentation will only happen on Windows Insider builds.)
+
+If this setting is not configured or enabled, the user can control experimentation in the PowerToys settings menu.
+
+If this setting is disabled, experimentation is not allowed.
+
+If this setting is not configured, experimentation is allowed.
+
+### Installer and Updates
+
+#### Disable per-user installation
+
+This policy configures whether PowerToys per-user installation is allowed or not.
+
+If enabled, per-user installation is not allowed.
+
+If disabled or not configured, per-user installation is allowed.
+
+You can set this policy only as Computer policy.
+#### Disable automatic downloads
+
+This policy configures whether automatic downloads of available updates are disabled or not. (On metered connections updates are never downloaded.)
+
+If enabled, automatic downloads are disabled.
+
+If disabled or not configured, the user is in control of automatic downloads setting.
+
+#### Suspend Action Center notification for new updates
+
+This policy configures whether the action center notification for new updates is suspended for 2 minor releases. (Example: if the installed version is v0.60.0, then the next notification is shown for the v0.63.* release.)
+
+If enabled, the notification is suspended.
+
+If disabled or not configured, the notification is shown.
+
+Note: The notification about new major versions is always displayed.
+
+
diff --git a/doc/images/disk-usage/PowerToys_install_dir.png b/doc/images/disk-usage/PowerToys_install_dir.png
new file mode 100644
index 0000000000..d8559a4b28
Binary files /dev/null and b/doc/images/disk-usage/PowerToys_install_dir.png differ
diff --git a/doc/images/disk-usage/add_remove_size_v0.66.png b/doc/images/disk-usage/add_remove_size_v0.66.png
new file mode 100644
index 0000000000..1792a77116
Binary files /dev/null and b/doc/images/disk-usage/add_remove_size_v0.66.png differ
diff --git a/doc/images/disk-usage/empty_disk_details.png b/doc/images/disk-usage/empty_disk_details.png
new file mode 100644
index 0000000000..376320830d
Binary files /dev/null and b/doc/images/disk-usage/empty_disk_details.png differ
diff --git a/doc/images/disk-usage/install_dir_size_v0.66.png b/doc/images/disk-usage/install_dir_size_v0.66.png
new file mode 100644
index 0000000000..9a3038d937
Binary files /dev/null and b/doc/images/disk-usage/install_dir_size_v0.66.png differ
diff --git a/doc/images/disk-usage/pwsh_v0.66.png b/doc/images/disk-usage/pwsh_v0.66.png
new file mode 100644
index 0000000000..854c154c05
Binary files /dev/null and b/doc/images/disk-usage/pwsh_v0.66.png differ
diff --git a/doc/images/disk-usage/used_disk_space_v0.66.png b/doc/images/disk-usage/used_disk_space_v0.66.png
new file mode 100644
index 0000000000..af687d9e43
Binary files /dev/null and b/doc/images/disk-usage/used_disk_space_v0.66.png differ
diff --git a/doc/images/icons/Paste As Plain Text.png b/doc/images/icons/Paste As Plain Text.png
new file mode 100644
index 0000000000..3ce90ef52d
Binary files /dev/null and b/doc/images/icons/Paste As Plain Text.png differ
diff --git a/doc/images/icons/Registry Preview.png b/doc/images/icons/Registry Preview.png
new file mode 100644
index 0000000000..ff2d58613c
Binary files /dev/null and b/doc/images/icons/Registry Preview.png differ
diff --git a/doc/images/tools/fancyzone-hit-test.png b/doc/images/tools/fancyzone-hit-test.png
new file mode 100644
index 0000000000..8886b2be5f
Binary files /dev/null and b/doc/images/tools/fancyzone-hit-test.png differ
diff --git a/doc/images/tools/fancyzones-zonable-tester.png b/doc/images/tools/fancyzones-zonable-tester.png
new file mode 100644
index 0000000000..4a10315456
Binary files /dev/null and b/doc/images/tools/fancyzones-zonable-tester.png differ
diff --git a/installer/PowerToysSetup/AlwaysOnTop.wxs b/installer/PowerToysSetup/AlwaysOnTop.wxs
new file mode 100644
index 0000000000..f98f84d987
--- /dev/null
+++ b/installer/PowerToysSetup/AlwaysOnTop.wxs
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Awake.wxs b/installer/PowerToysSetup/Awake.wxs
new file mode 100644
index 0000000000..7228069434
--- /dev/null
+++ b/installer/PowerToysSetup/Awake.wxs
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/ColorPicker.wxs b/installer/PowerToysSetup/ColorPicker.wxs
new file mode 100644
index 0000000000..088c94e19e
--- /dev/null
+++ b/installer/PowerToysSetup/ColorPicker.wxs
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Common.wxi b/installer/PowerToysSetup/Common.wxi
new file mode 100644
index 0000000000..76dcb2ac9d
--- /dev/null
+++ b/installer/PowerToysSetup/Common.wxi
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Core.wxs b/installer/PowerToysSetup/Core.wxs
new file mode 100644
index 0000000000..330ff1cd76
--- /dev/null
+++ b/installer/PowerToysSetup/Core.wxs
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ INSTALLDESKTOPSHORTCUT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/FancyZones.wxs b/installer/PowerToysSetup/FancyZones.wxs
new file mode 100644
index 0000000000..1a29f8df40
--- /dev/null
+++ b/installer/PowerToysSetup/FancyZones.wxs
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/FileExplorerPreview.wxs b/installer/PowerToysSetup/FileExplorerPreview.wxs
new file mode 100644
index 0000000000..ba819ad22c
--- /dev/null
+++ b/installer/PowerToysSetup/FileExplorerPreview.wxs
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/FileLocksmith.wxs b/installer/PowerToysSetup/FileLocksmith.wxs
new file mode 100644
index 0000000000..f2417ed0f0
--- /dev/null
+++ b/installer/PowerToysSetup/FileLocksmith.wxs
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Hosts.wxs b/installer/PowerToysSetup/Hosts.wxs
new file mode 100644
index 0000000000..5a63b632f3
--- /dev/null
+++ b/installer/PowerToysSetup/Hosts.wxs
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/ImageResizer.wxs b/installer/PowerToysSetup/ImageResizer.wxs
new file mode 100644
index 0000000000..5534e838c8
--- /dev/null
+++ b/installer/PowerToysSetup/ImageResizer.wxs
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Images/logo.png b/installer/PowerToysSetup/Images/logo.png
index d130d131bd..c9f9405405 100644
Binary files a/installer/PowerToysSetup/Images/logo.png and b/installer/PowerToysSetup/Images/logo.png differ
diff --git a/installer/PowerToysSetup/Images/logo150.png b/installer/PowerToysSetup/Images/logo150.png
index 7ff16cbc02..35e757d8e5 100644
Binary files a/installer/PowerToysSetup/Images/logo150.png and b/installer/PowerToysSetup/Images/logo150.png differ
diff --git a/installer/PowerToysSetup/Images/logo44.png b/installer/PowerToysSetup/Images/logo44.png
index 78b8ecf614..b931931dff 100644
Binary files a/installer/PowerToysSetup/Images/logo44.png and b/installer/PowerToysSetup/Images/logo44.png differ
diff --git a/installer/PowerToysSetup/KeyboardManager.wxs b/installer/PowerToysSetup/KeyboardManager.wxs
new file mode 100644
index 0000000000..925588c41e
--- /dev/null
+++ b/installer/PowerToysSetup/KeyboardManager.wxs
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/MeasureTool.wxs b/installer/PowerToysSetup/MeasureTool.wxs
new file mode 100644
index 0000000000..879a3246ac
--- /dev/null
+++ b/installer/PowerToysSetup/MeasureTool.wxs
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/MonacoSRC.wxs b/installer/PowerToysSetup/MonacoSRC.wxs
new file mode 100644
index 0000000000..b8a997ac44
--- /dev/null
+++ b/installer/PowerToysSetup/MonacoSRC.wxs
@@ -0,0 +1,1059 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/installer/PowerToysSetup/MouseUtils.wxs b/installer/PowerToysSetup/MouseUtils.wxs
new file mode 100644
index 0000000000..933b6b115f
--- /dev/null
+++ b/installer/PowerToysSetup/MouseUtils.wxs
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/PastePlain.wxs b/installer/PowerToysSetup/PastePlain.wxs
new file mode 100644
index 0000000000..a0a92e4603
--- /dev/null
+++ b/installer/PowerToysSetup/PastePlain.wxs
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/PowerAccent.wxs b/installer/PowerToysSetup/PowerAccent.wxs
new file mode 100644
index 0000000000..98d78ca856
--- /dev/null
+++ b/installer/PowerToysSetup/PowerAccent.wxs
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/PowerRename.wxs b/installer/PowerToysSetup/PowerRename.wxs
new file mode 100644
index 0000000000..5b5f48f1e7
--- /dev/null
+++ b/installer/PowerToysSetup/PowerRename.wxs
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/PowerToys.wxs b/installer/PowerToysSetup/PowerToys.wxs
index 0818170273..bb4d820ba4 100644
--- a/installer/PowerToysSetup/PowerToys.wxs
+++ b/installer/PowerToysSetup/PowerToys.wxs
@@ -1,25 +1,13 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
+
+
+
+
-
+
+
+
+
- TargetPowerToysVersion >= DetectedPowerToysVersion OR WixBundleInstalled
+
+
+
+ MinimumVersion >= DetectedPowerToysVersion
+ TargetPowerToysVersion >= DetectedPowerToysUserVersion OR WixBundleInstalled
+
+ MinimumVersion >= DetectedPowerToysUserVersion
+ TargetPowerToysVersion >= DetectedPowerToysVersion OR WixBundleInstalled
+
@@ -61,7 +64,7 @@
Id="TerminatePowerToys"
SourceFile="terminate_powertoys.cmd"
Permanent="yes"
- PerMachine="yes"
+ PerMachine="$(var.PerMachineYesNo)"
Vital="no">
diff --git a/installer/PowerToysSetup/PowerToysBootstrapper.wixproj b/installer/PowerToysSetup/PowerToysBootstrapper.wixproj
index f03cc88b35..ca71607595 100644
--- a/installer/PowerToysSetup/PowerToysBootstrapper.wixproj
+++ b/installer/PowerToysSetup/PowerToysBootstrapper.wixproj
@@ -1,4 +1,4 @@
-
+
PowerToysBootstrapper
{31d72625-43c1-41b1-b784-bce4a8dc5543}
+
+ $(DefineConstants);PerUser=true
+
+
+ $(DefineConstants);PerUser=false
+
Release
x64
@@ -20,8 +26,10 @@
PowerToysSetup-$(Version)-$(Platform)
Bundle
True
- PowerToysSetup-$(Version)-$(Platform)
- $(Platform)\$(Configuration)\
+ PowerToysSetup-$(Version)-$(Platform)
+ PowerToysUserSetup-$(Version)-$(Platform)
+ $(Platform)\$(Configuration)\MachineSetup
+ $(Platform)\$(Configuration)\UserSetup
obj\$(Platform)\$(Configuration)\
diff --git a/installer/PowerToysSetup/PowerToysInstaller.wixproj b/installer/PowerToysSetup/PowerToysInstaller.wixproj
index 4c8858c5c7..ef1e0af9ae 100644
--- a/installer/PowerToysSetup/PowerToysInstaller.wixproj
+++ b/installer/PowerToysSetup/PowerToysInstaller.wixproj
@@ -11,8 +11,8 @@
simulate the build pipeline doing that for you. -->
IF NOT DEFINED IsPipeline (
call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64 -winsdk=10.0.19041.0
-SET PTRoot=..\..\..\..
-call "..\..\publish.cmd" x64
+SET PTRoot=..\..\..\..\..
+call "..\..\..\publish.cmd" x64
)
@@ -20,20 +20,50 @@ call "..\..\publish.cmd" x64
Version=$(Version);MonacoSRCHarvestPath=$(ProjectDir)..\..\ARM64\$(Configuration)\common\FilePreviewCommon\monaco\monacoSRC
IF NOT DEFINED IsPipeline (
call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=arm64 -host_arch=amd64 -winsdk=10.0.19041.0
-SET PTRoot=..\..\..\..
-call "..\..\publish.cmd" arm64
+SET PTRoot=..\..\..\..\..
+call "..\..\..\publish.cmd" arm64
)
Always
- call move /Y ..\..\Product.wxs.bk ..\..\Product.wxs
- call move /Y ..\..\..\PowerToysSetupCustomActions\DepsFilesLists.h.bk ..\..\..\PowerToysSetupCustomActions\DepsFilesLists.h
+ call move /Y ..\..\..\AlwaysOnTop.wxs.bk ..\..\..\AlwaysOnTop.wxs
+ call move /Y ..\..\..\Awake.wxs.bk ..\..\..\Awake.wxs
+ call move /Y ..\..\..\ColorPicker.wxs.bk ..\..\..\ColorPicker.wxs
+ call move /Y ..\..\..\Core.wxs.bk ..\..\..\Core.wxs
+ call move /Y ..\..\..\FancyZones.wxs.bk ..\..\..\FancyZones.wxs
+ call move /Y ..\..\..\FileExplorerPreview.wxs.bk ..\..\..\FileExplorerPreview.wxs
+ call move /Y ..\..\..\FileLocksmith.wxs.bk ..\..\..\FileLocksmith.wxs
+ call move /Y ..\..\..\Hosts.wxs.bk ..\..\..\Hosts.wxs
+ call move /Y ..\..\..\ImageResizer.wxs.bk ..\..\..\ImageResizer.wxs
+ call move /Y ..\..\..\KeyboardManager.wxs.bk ..\..\..\KeyboardManager.wxs
+ call move /Y ..\..\..\MeasureTool.wxs.bk ..\..\..\MeasureTool.wxs
+ call move /Y ..\..\..\MouseUtils.wxs.bk ..\..\..\MouseUtils.wxs
+ call move /Y ..\..\..\PowerAccent.wxs.bk ..\..\..\PowerAccent.wxs
+ call move /Y ..\..\..\PowerRename.wxs.bk ..\..\..\PowerRename.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
+ call move /Y ..\..\..\Run.wxs.bk ..\..\..\Run.wxs
+ call move /Y ..\..\..\Settings.wxs.bk ..\..\..\Settings.wxs
+ call move /Y ..\..\..\ShortcutGuide.wxs.bk ..\..\..\ShortcutGuide.wxs
+ call move /Y ..\..\..\TextExtractor.wxs.bk ..\..\..\TextExtractor.wxs
+ call move /Y ..\..\..\Tools.wxs.bk ..\..\..\Tools.wxs
+ call move /Y ..\..\..\VideoConference.wxs.bk ..\..\..\VideoConference.wxs
+ call move /Y ..\..\..\WinAppSDK.wxs.bk ..\..\..\WinAppSDK.wxs
+ call move /Y ..\..\..\..\PowerToysSetupCustomActions\DepsFilesLists.h.bk ..\..\..\..\PowerToysSetupCustomActions\DepsFilesLists.h
PowerToysInstaller
+
+ $(DefineConstants);PerUser=true
+
+
+ $(DefineConstants);PerUser=false
+
+
Release
@@ -41,15 +71,22 @@ call "..\..\publish.cmd" arm64
3.10
022a9d30-7c4f-416d-a9df-5ff2661cc0ad
2.0
- PowerToysSetup-$(Version)-$(Platform)
+ PowerToysSetup-$(Version)-$(Platform)
+ PowerToysUserSetup-$(Version)-$(Platform)
Package
True
+
+
+ ICE91
+ 1026;1076
- $(Platform)\$(Configuration)\
- obj\$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\MachineSetup
+ $(Platform)\$(Configuration)\UserSetup
+ obj\$(Platform)\$(Configuration)\MachineSetup
+ obj\$(Platform)\$(Configuration)\UserSetup
ICE40
@@ -62,7 +99,34 @@ call "..\..\publish.cmd" arm64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -112,18 +176,19 @@ call "..\..\publish.cmd" arm64
- -->
-
+ SuppressFragments="false"
+ SuppressRegistry="false"
+ SuppressRootDirectory="true"/>
+ -->
+
\ No newline at end of file
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index c33f2157eb..66320a763e 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -2,34 +2,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ UpgradeCode="$(var.UpgradeCodeGUID)">
-
+
+
-
+
@@ -185,19 +48,44 @@
+
+
+ Description="Contains all PowerToys features.">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Installed AND NOT (_REMOVE_ALL="Yes")
Installed AND NOT (_REMOVE_ALL="Yes")
+
@@ -230,13 +119,13 @@
-
-
+
+
-
+
""]]>
@@ -244,6 +133,7 @@
DEFAULTBOOTSTRAPPERINSTALLFOLDER OR PREVIOUSINSTALLFOLDER = ""]]>
+
@@ -258,6 +148,9 @@
NOT Installed and CREATESCHEDULEDTASK = 1
+
+ NOT Installed
+
NOT Installed
@@ -291,9 +184,8 @@
Installed AND (REMOVE="ALL")
-
- Installed AND (REMOVE="ALL")
-
+
+
Installed AND (REMOVE="ALL")
@@ -524,6 +416,13 @@
DllEntry="UnRegisterContextMenuPackagesCA"
/>
+
+
@@ -534,9 +433,10 @@
+
-
+
@@ -560,13 +460,16 @@
+
+
+
-
-
-
+
+
+
@@ -597,6 +500,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -629,83 +545,62 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -719,1754 +614,16 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WINDOWSBUILDNUMBER >= 19041
-
-
-
-
-
-
-
-
-
-
-
-
-
- WINDOWSBUILDNUMBER >= 19041
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- INSTALLDESKTOPSHORTCUT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/installer/PowerToysSetup/RegistryPreview.wxs b/installer/PowerToysSetup/RegistryPreview.wxs
new file mode 100644
index 0000000000..74804f6c6e
--- /dev/null
+++ b/installer/PowerToysSetup/RegistryPreview.wxs
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Resources.wxs b/installer/PowerToysSetup/Resources.wxs
new file mode 100644
index 0000000000..351bd05393
--- /dev/null
+++ b/installer/PowerToysSetup/Resources.wxs
@@ -0,0 +1,474 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Run.wxs b/installer/PowerToysSetup/Run.wxs
new file mode 100644
index 0000000000..9d22b64156
--- /dev/null
+++ b/installer/PowerToysSetup/Run.wxs
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Settings.wxs b/installer/PowerToysSetup/Settings.wxs
new file mode 100644
index 0000000000..698575cbcf
--- /dev/null
+++ b/installer/PowerToysSetup/Settings.wxs
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/ShortcutGuide.wxs b/installer/PowerToysSetup/ShortcutGuide.wxs
new file mode 100644
index 0000000000..2053ffae34
--- /dev/null
+++ b/installer/PowerToysSetup/ShortcutGuide.wxs
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/TextExtractor.wxs b/installer/PowerToysSetup/TextExtractor.wxs
new file mode 100644
index 0000000000..3afbb2a5e1
--- /dev/null
+++ b/installer/PowerToysSetup/TextExtractor.wxs
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Tools.wxs b/installer/PowerToysSetup/Tools.wxs
new file mode 100644
index 0000000000..a9fe0bf306
--- /dev/null
+++ b/installer/PowerToysSetup/Tools.wxs
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/VideoConference.wxs b/installer/PowerToysSetup/VideoConference.wxs
new file mode 100644
index 0000000000..c2b6915e5c
--- /dev/null
+++ b/installer/PowerToysSetup/VideoConference.wxs
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+ WINDOWSBUILDNUMBER >= 19041
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ WINDOWSBUILDNUMBER >= 19041
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/WinAppSDK.wxs b/installer/PowerToysSetup/WinAppSDK.wxs
new file mode 100644
index 0000000000..cb20c8cfa9
--- /dev/null
+++ b/installer/PowerToysSetup/WinAppSDK.wxs
@@ -0,0 +1,514 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/generateAllFileComponents.ps1 b/installer/PowerToysSetup/generateAllFileComponents.ps1
new file mode 100644
index 0000000000..93b35f7684
--- /dev/null
+++ b/installer/PowerToysSetup/generateAllFileComponents.ps1
@@ -0,0 +1,214 @@
+[CmdletBinding()]
+Param(
+ [Parameter(Mandatory = $True, Position = 1)]
+ [string]$platform,
+ [Parameter(Mandatory = $False, Position = 2)]
+ [string]$installscopeperuser = "false"
+)
+
+if ($platform -ceq "arm64") {
+ $platform = "ARM64"
+}
+
+if ($installscopeperuser -eq "true") {
+ $registryroot = "HKCU"
+} else {
+ $registryroot = "HKLM"
+}
+
+#AlwaysOnTop
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName AlwaysOnTopFiles -wxsFilePath $PSScriptRoot\AlwaysOnTop.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\AlwaysOnTop"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""AlwaysOnTopFiles"" -wxsFilePath $PSScriptRoot\AlwaysOnTop.wxs -regroot $registryroot"
+
+#AwakeFiles
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\Awake\PowerToys.Awake.deps.json"" -fileListName AwakeFiles -wxsFilePath $PSScriptRoot\Awake.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName AwakeImagesFiles -wxsFilePath $PSScriptRoot\Awake.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\Awake\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""AwakeFiles"" -wxsFilePath $PSScriptRoot\Awake.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""AwakeImagesFiles"" -wxsFilePath $PSScriptRoot\Awake.wxs -regroot $registryroot"
+
+#ColorPicker
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\ColorPicker\PowerToys.ColorPickerUI.deps.json"" -fileListName ColorPickerFiles -wxsFilePath $PSScriptRoot\ColorPicker.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ColorPickerResourcesFiles -wxsFilePath $PSScriptRoot\ColorPicker.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\ColorPicker\Resources"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ColorPickerFiles"" -wxsFilePath $PSScriptRoot\ColorPicker.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ColorPickerResourcesFiles"" -wxsFilePath $PSScriptRoot\ColorPicker.wxs -regroot $registryroot"
+
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\ColorPicker\PowerToys.ColorPickerUI.deps.json"" -fileListName ColorPickerFiles -wxsFilePath $PSScriptRoot\ColorPicker.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ColorPickerFiles"" -wxsFilePath $PSScriptRoot\ColorPicker.wxs -regroot $registryroot"
+
+#FancyZones
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\FancyZones\PowerToys.FancyZonesEditor.deps.json"" -fileListName FancyZonesFiles -wxsFilePath $PSScriptRoot\FancyZones.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FancyZonesFiles"" -wxsFilePath $PSScriptRoot\FancyZones.wxs -regroot $registryroot"
+
+#FileExplorerAdd-ons
+#TODO: There are multiple .deps.json files, make sure it works as expected
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\FileExplorerPreview\PowerToys.SvgThumbnailProvider.deps.json"" -fileListName PowerPreviewFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName MonacoCustomLanguagesFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\FileExplorerPreview\customLanguages"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerPreviewFiles"" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""MonacoCustomLanguagesFiles"" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot"
+
+#FileLocksmith
+#TODO: There are multiple .deps.json files, make sure it works as expected
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\FileLocksmith\PowerToys.FileLocksmithUI.deps.json"" -fileListName FileLocksmithFiles -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -isWinAppSdkProj 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName FileLocksmithAssetsFiles -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\FileLocksmith\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FileLocksmithFiles"" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FileLocksmithAssetsFiles"" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -regroot $registryroot"
+
+#Hosts
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\Hosts\PowerToys.Hosts.deps.json"" -fileListName HostsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -isWinAppSdkProj 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName HostsAssetsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\Hosts\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""HostsFiles"" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""HostsAssetsFiles"" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot"
+
+#ImageResizer
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\ImageResizer\PowerToys.ImageResizer.deps.json"" -fileListName ImageResizerFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ImageResizerAssetsFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\ImageResizer\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ImageResizerFiles"" -wxsFilePath $PSScriptRoot\ImageResizer.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ImageResizerAssetsFiles"" -wxsFilePath $PSScriptRoot\ImageResizer.wxs -regroot $registryroot"
+
+#MouseUtils
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName MouseUtilsFiles -wxsFilePath $PSScriptRoot\MouseUtils.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\MouseUtils\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""MouseUtilsFiles"" -wxsFilePath $PSScriptRoot\MouseUtils.wxs -regroot $registryroot"
+#MouseJumpUI
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\MouseUtils\MouseJumpUI\PowerToys.MouseJumpUI.deps.json"" -fileListName MouseJumpUIFiles -wxsFilePath $PSScriptRoot\MouseUtils.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""MouseJumpUIFiles"" -wxsFilePath $PSScriptRoot\MouseUtils.wxs -regroot $registryroot"
+
+#MeasureTool
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\MeasureTool\PowerToys.MeasureToolUI.deps.json"" -fileListName MeasureToolFiles -wxsFilePath $PSScriptRoot\MeasureTool.wxs -isWinAppSdkProj 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""MeasureToolFiles"" -wxsFilePath $PSScriptRoot\MeasureTool.wxs -regroot $registryroot"
+
+#PowerAccent
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\PowerAccent\PowerToys.PowerAccent.deps.json"" -fileListName PowerAccentFiles -wxsFilePath $PSScriptRoot\PowerAccent.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerAccentFiles"" -wxsFilePath $PSScriptRoot\PowerAccent.wxs -regroot $registryroot"
+
+#PowerRename
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName PowerRenameFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\PowerRename\"" -isWinAppSdkProj 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName PowerRenameAssetsFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\PowerRename\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerRenameFiles"" -wxsFilePath $PSScriptRoot\PowerRename.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerRenameAssetsFiles"" -wxsFilePath $PSScriptRoot\PowerRename.wxs -regroot $registryroot"
+
+#RegistryPreview
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\RegistryPreview\PowerToys.RegistryPreview.deps.json"" -fileListName RegistryPreviewFiles -wxsFilePath $PSScriptRoot\RegistryPreview.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName RegistryPreviewAssetsFiles -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\RegistryPreview\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""RegistryPreviewFiles"" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""RegistryPreviewAssetsFiles"" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -regroot $registryroot"
+
+#Run
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\PowerToys.PowerLauncher.deps.json"" -fileListName launcherFiles -wxsFilePath $PSScriptRoot\Run.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName launcherImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""launcherFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""launcherImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+## Plugins
+###Calculator
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.deps.json"" -fileListName calcComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName calcImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Calculator\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""calcComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""calcImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Folder
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Folder\Microsoft.Plugin.Folder.deps.json"" -fileListName FolderComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName FolderImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Folder\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FolderComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FolderImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Program
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Program\Microsoft.Plugin.Program.deps.json"" -fileListName ProgramComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ProgramImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Program\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ProgramComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ProgramImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Shell
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Shell\Microsoft.Plugin.Shell.deps.json"" -fileListName ShellComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ShellImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Shell\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ShellComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ShellImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Indexer
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Indexer\Microsoft.Plugin.Indexer.deps.json"" -fileListName IndexerComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName IndexerImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Indexer\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""IndexerComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""IndexerImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###UnitConverter
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.deps.json"" -fileListName UnitConvCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName UnitConvImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\UnitConverter\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""UnitConvCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""UnitConvImagesCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###WebSearch
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WebSearch\Community.PowerToys.Run.Plugin.WebSearch.deps.json"" -fileListName WebSrchCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WebSrchImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WebSearch\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WebSrchCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WebSrchImagesCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###History
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\History\Microsoft.PowerToys.Run.Plugin.History.deps.json"" -fileListName HistoryPluginComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName HistoryPluginImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\History\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""HistoryPluginComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""HistoryPluginImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Uri
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Uri\Microsoft.Plugin.Uri.deps.json"" -fileListName UriComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName UriImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Uri\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""UriComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""UriImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###VSCodeWorkspaces
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.deps.json"" -fileListName VSCWrkCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName VSCWrkImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\VSCodeWorkspaces\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""VSCWrkCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""VSCWrkImagesCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###WindowWalker
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowWalker\Microsoft.Plugin.WindowWalker.deps.json"" -fileListName WindowWlkrCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WindowWlkrImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowWalker\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WindowWlkrCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WindowWlkrImagesCompFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###OneNote
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.deps.json"" -fileListName OneNoteComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName OneNoteImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\OneNote\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""OneNoteComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""OneNoteImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Registry
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.deps.json"" -fileListName RegistryComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName RegistryImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Registry\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""RegistryComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""RegistryImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###Service
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Service\Microsoft.PowerToys.Run.Plugin.Service.deps.json"" -fileListName ServiceComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ServiceImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\Service\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ServiceComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ServiceImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###System
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\System\Microsoft.PowerToys.Run.Plugin.System.deps.json"" -fileListName SystemComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName SystemImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\System\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SystemComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SystemImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###TimeDate
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.deps.json"" -fileListName TimeDateComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName TimeDateImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\TimeDate\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""TimeDateComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""TimeDateImagesComponentFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###WindowsSettings
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.deps.json"" -fileListName WinSetCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WinSetImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowsSettings\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinSetCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinSetImagesCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+###WindowsTerminal
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.deps.json"" -fileListName WinTermCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WinTermImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowsTerminal\Images"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinTermCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinTermImagesCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
+## Plugins
+
+#ShortcutGuide
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\ShortcutGuide\ShortcutGuide\svgs\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""ShortcutGuideSvgFiles"" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -regroot $registryroot"
+
+#TextExtractor
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\PowerOCR\PowerToys.PowerOCR.deps.json"" -fileListName TextExtractorFiles -wxsFilePath $PSScriptRoot\TextExtractor.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""TextExtractorFiles"" -wxsFilePath $PSScriptRoot\TextExtractor.wxs -regroot $registryroot"
+
+#Settings
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\Settings\PowerToys.Settings.deps.json"" -fileListName SettingsV2Files -wxsFilePath $PSScriptRoot\Settings.wxs"
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\Settings\Assets\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName SettingsV2AssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\Settings\Assets\Modules\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName SettingsV2OOBEAssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\Settings\Assets\Modules\OOBE\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName SettingsV2OOBEAssetsFluentIconsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\Settings\Assets\FluentIcons\"""
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SettingsV2Files"" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SettingsV2AssetsFiles"" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SettingsV2AssetsModulesFiles"" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SettingsV2OOBEAssetsModulesFiles"" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot"
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""SettingsV2OOBEAssetsFluentIconsFiles"" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot"
+
+#WinAppSdk
+Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinAppSDKFiles"" -wxsFilePath $PSScriptRoot\WinAppSDK.wxs -regroot $registryroot"
diff --git a/installer/PowerToysSetup/generateFileComponents.ps1 b/installer/PowerToysSetup/generateFileComponents.ps1
new file mode 100644
index 0000000000..ad223711e8
--- /dev/null
+++ b/installer/PowerToysSetup/generateFileComponents.ps1
@@ -0,0 +1,56 @@
+[CmdletBinding()]
+Param(
+ [Parameter(Mandatory = $True, Position = 1)]
+ [string]$fileListName,
+ [Parameter(Mandatory = $True, Position = 2)]
+ [string]$wxsFilePath,
+ [Parameter(Mandatory = $True, Position = 3)]
+ [string]$regroot
+)
+
+$wxsFile = Get-Content $wxsFilePath;
+
+$wxsFile | ForEach-Object {
+ if ($_ -match "(") {
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'fileList',
+ Justification = 'variable is used in another scope')]
+
+ $fileList = $matches[2] -split ';'
+ return
+ }
+}
+
+$componentId = "$($fileListName)_Component"
+
+$componentDefs = "`r`n"
+$componentDefs +=
+@"
+
+
+
+ `r`n
+"@
+
+foreach ($file in $fileList) {
+ $fileTmp = $file -replace "-", "_"
+ $componentDefs +=
+@"
+ `r`n
+"@
+}
+
+$componentDefs +=
+@"
+ `r`n
+"@
+
+$wxsFile = $wxsFile -replace "\s+()", $componentDefs
+
+$componentRef =
+@"
+
+"@
+
+$wxsFile = $wxsFile -replace "\s+()", "$componentRef`r`n "
+
+Set-Content -Path $wxsFilePath -Value $wxsFile
\ No newline at end of file
diff --git a/installer/PowerToysSetup/generateFileList.ps1 b/installer/PowerToysSetup/generateFileList.ps1
new file mode 100644
index 0000000000..7e0d8548a0
--- /dev/null
+++ b/installer/PowerToysSetup/generateFileList.ps1
@@ -0,0 +1,84 @@
+[CmdletBinding()]
+Param(
+ [Parameter(Mandatory = $True, Position = 1)]
+ [AllowEmptyString()]
+ [string]$fileDepsJson,
+ [Parameter(Mandatory = $True, Position = 2)]
+ [string]$fileListName,
+ [Parameter(Mandatory = $True, Position = 3)]
+ [string]$wxsFilePath,
+ # If there is no deps.json file, just pass path to files
+ [Parameter(Mandatory = $False, Position = 4)]
+ [string]$depsPath,
+ # launcher plugins are being loaded into launcher process,
+ # so there are some additional dependencies to skip
+ [Parameter(Mandatory = $False, Position = 5)]
+ [bool]$isLauncherPlugin,
+ # Skip winAppSDK dlls as those are hard-linked
+ [Parameter(Mandatory = $False, Position = 6)]
+ [bool]$isWinAppSdkProj
+)
+
+$fileWxs = Get-Content $wxsFilePath;
+
+#Skip PowerToysInterop files
+$coreWxs = Get-Content $PSScriptRoot/"Core.wxs"
+$coreWxs | ForEach-Object {
+ if ($_ -match "(") {
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'fileList',
+ Justification = 'variable is used in another scope')]
+
+ $interopFilesList = $matches[2] -split ';'
+ return
+ }
+}
+
+#Skip WinAppSdk files
+if ($isWinAppSdkProj -eq $True) {
+ $winAppSDKWxs = Get-Content $PSScriptRoot/"WinAppSDK.wxs"
+ $winAppSDKWxs | ForEach-Object {
+ if ($_ -match "(") {
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'fileList',
+ Justification = 'variable is used in another scope')]
+
+ $winAppSDKfilesList = $matches[2] -split ';'
+ return
+ }
+ }
+}
+
+$fileExclusionList = @("*Test*", "*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe") + $interopFilesList + $winAppSDKfilesList
+
+$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*png", "*gif", "*ico", "*cur", "*svg", "index.html", "reg.js", "monacoSpecialLanguages.js", "resources.pri", "NLog.config")
+
+$dllsToIgnore = @("System.CodeDom.dll", "WindowsBase.dll")
+
+if ($fileDepsJson -eq [string]::Empty) {
+ $fileDepsRoot = $depsPath
+} else {
+ $fileDepsRoot = (Get-ChildItem $fileDepsJson).Directory.FullName
+ $depsJson = Get-Content $fileDepsJson | ConvertFrom-Json
+
+ $runtimeList = ([array]$depsJson.targets.PSObject.Properties)[-1].Value.PSObject.Properties | Where-Object {
+ $_.Name -match "runtimepack.*Runtime"
+ };
+
+ $runtimeList | ForEach-Object {
+ $_.Value.PSObject.Properties.Value | ForEach-Object {
+ $fileExclusionList += $_.PSObject.Properties.Name
+ }
+ }
+}
+
+$fileExclusionList = $fileExclusionList | Where-Object {$_ -notin $dllsToIgnore}
+
+if ($isLauncherPlugin -eq $True) {
+ $fileInclusionList += @("*.deps.json")
+ $fileExclusionList += @("Ijwhost.dll", "PowerToys.Common.UI.dll", "PowerToys.GPOWrapper.dll", "PowerToys.GPOWrapperProjection.dll", "PowerToys.PowerLauncher.Telemetry.dll", "PowerToys.ManagedCommon.dll", "PowerToys.Settings.UI.Lib.dll", "Wox.Infrastructure.dll", "Wox.Plugin.dll")
+}
+
+$fileList = Get-ChildItem $fileDepsRoot -Include $fileInclusionList -Exclude $fileExclusionList -File -Name
+
+$fileWxs = $fileWxs -replace "(<\?define $($fileListName)=)", "
#include "../../src/common/logger/logger.h"
+#include "../../src/common/utils/gpo.h"
#include "../../src/common/utils/MsiUtils.h"
#include "../../src/common/utils/modulesRegistry.h"
#include "../../src/common/updating/installer.h"
@@ -34,24 +35,6 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
-struct WcaSink : spdlog::sinks::base_sink
-{
- virtual void sink_it_(const spdlog::details::log_msg& msg) override
- {
- WcaLog(LOGMSG_STANDARD, msg.payload.data());
- }
- virtual void flush_() override
- {
- // we don't need to flush wca log manually
- }
-};
-
-void initSystemLogger()
-{
- static std::once_flag initLoggerFlag;
- std::call_once(initLoggerFlag, []() { Logger::init(std::vector{ std::make_shared() }); });
-}
-
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
{
DWORD len = 0;
@@ -68,9 +51,35 @@ HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
LExit:
return hr;
}
+
+UINT __stdcall CheckGPOCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+
+ hr = WcaInitialize(hInstall, "CheckGPOCA");
+ ExitOnFailure(hr, "Failed to initialize");
+
+ LPWSTR currentScope = nullptr;
+ hr = WcaGetProperty(L"InstallScope", ¤tScope);
+
+ if(std::wstring{ currentScope } == L"perUser")
+ {
+ if (powertoys_gpo::getDisablePerUserInstallationValue() == powertoys_gpo::gpo_rule_configured_enabled)
+ {
+ PMSIHANDLE hRecord = MsiCreateRecord(0);
+ MsiRecordSetString(hRecord, 0, TEXT("The system administrator has disabled per-user installation."));
+ MsiProcessMessage(hInstall, static_cast(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
+ hr = E_ABORT;
+ }
+ }
+
+LExit:
+ UINT er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
+
UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
- initSystemLogger();
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
@@ -85,14 +94,14 @@ UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
if (!changeSet.apply())
{
- WcaLog(LOGMSG_STANDARD, "Couldn't apply registry changeSet");
+ Logger::error(L"Couldn't apply registry changeSet");
failedToApply = true;
}
}
if (!failedToApply)
{
- WcaLog(LOGMSG_STANDARD, "All registry changeSets applied successfully");
+ Logger::info(L"All registry changeSets applied successfully");
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
@@ -101,7 +110,6 @@ LExit:
UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
- initSystemLogger();
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
@@ -131,14 +139,14 @@ UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall)
if (auto msix = RcResource::create(IDR_BIN_MSIX_HELLO_PACKAGE, L"BIN", DLL_HANDLE))
{
- WcaLog(LOGMSG_STANDARD, "Extracted MSIX");
+ Logger::info(L"Extracted MSIX");
// TODO: Use to activate embedded MSIX
const auto msix_path = std::filesystem::temp_directory_path() / "hello_package.msix";
if (!msix->saveAsFile(msix_path))
{
ExitOnFailure(hr, "Failed to save msix");
}
- WcaLog(LOGMSG_STANDARD, "Saved MSIX");
+ Logger::info(L"Saved MSIX");
using namespace winrt::Windows::Management::Deployment;
using namespace winrt::Windows::Foundation;
@@ -150,7 +158,7 @@ UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall)
ExitOnFailure(hr, "Failed to AddPackage");
}
- WcaLog(LOGMSG_STANDARD, "MSIX[s] were installed!");
+ Logger::info(L"MSIX[s] were installed!");
}
else
{
@@ -181,11 +189,11 @@ UINT __stdcall UninstallEmbeddedMSIXCA(MSIHANDLE hInstall)
auto result = pm.RemovePackageAsync(p.Id().FullName()).get();
if (result)
{
- WcaLog(LOGMSG_STANDARD, "MSIX was uninstalled!");
+ Logger::info(L"MSIX was uninstalled!");
}
else
{
- WcaLog(LOGMSG_STANDARD, "Couldn't uninstall MSIX!");
+ Logger::error(L"Couldn't uninstall MSIX!");
}
}
@@ -227,7 +235,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "CreateScheduledTaskCA");
ExitOnFailure(hr, "Failed to initialize");
- WcaLog(LOGMSG_STANDARD, "Initialized.");
+ Logger::info(L"CreateScheduledTaskCA Initialized.");
// ------------------------------------------------------
// Get the Domain/Username for the trigger.
@@ -246,7 +254,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
wcscat_s(username_domain, L"\\");
wcscat_s(username_domain, username);
- WcaLog(LOGMSG_STANDARD, "Current user detected: %ls", username_domain);
+ Logger::info(L"Current user detected: {}", username_domain);
// Task Name.
wstrTaskName = L"Autorun for ";
@@ -264,7 +272,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
nullptr,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
- (void**)&pService);
+ reinterpret_cast(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
@@ -286,7 +294,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
pRootFolder->Release();
ExitOnFailure(hr, "Cannot create PowerToys task folder: %x", hr);
}
- WcaLog(LOGMSG_STANDARD, "PowerToys task folder created.");
+ Logger::info(L"PowerToys task folder created.");
}
// If the same task exists, remove it.
@@ -334,7 +342,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot put the trigger ID: %x", hr);
+ Logger::error(L"Cannot put the trigger ID: {}", hr);
}
// Timing issues may make explorer not be started when the task runs.
@@ -342,7 +350,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
hr = pLogonTrigger->put_Delay(_bstr_t(L"PT03S"));
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot put the trigger delay: %x", hr);
+ Logger::error(L"Cannot put the trigger delay: {}", hr);
}
// Define the user. The task will execute when the user logs on.
@@ -383,19 +391,19 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
hr = pPrincipal->put_Id(_bstr_t(L"Principal1"));
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot put the principal ID: %x", hr);
+ Logger::error(L"Cannot put the principal ID: {}", hr);
}
hr = pPrincipal->put_UserId(_bstr_t(username_domain));
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot put principal user Id: %x", hr);
+ Logger::error(L"Cannot put principal user Id: {}", hr);
}
hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot put principal logon type: %x", hr);
+ Logger::error(L"Cannot put principal logon type: {}", hr);
}
// Run the task with the highest available privileges.
@@ -419,7 +427,7 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
ExitOnFailure(hr, "Error saving the Task : %x", hr);
}
- WcaLog(LOGMSG_STANDARD, "Scheduled task created for the current user.");
+ Logger::info(L"Scheduled task created for the current user.");
LExit:
ReleaseStr(wszExecutablePath);
@@ -480,7 +488,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
ExitOnFailure(hr, "Failed to initialize");
- WcaLog(LOGMSG_STANDARD, "Initialized.");
+ Logger::info(L"RemoveScheduledTasksCA Initialized.");
// COM and Security Initialization is expected to have been done by the MSI.
// It couldn't be done in the DLL, anyway.
@@ -490,7 +498,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
nullptr,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
- (void**)&pService);
+ reinterpret_cast(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
@@ -503,7 +511,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
if (FAILED(hr))
{
// Folder doesn't exist. No need to delete anything.
- WcaLog(LOGMSG_STANDARD, "The PowerToys scheduled task folder wasn't found. Nothing to delete.");
+ Logger::info(L"The PowerToys scheduled task folder wasn't found. Nothing to delete.");
hr = S_OK;
ExitFunction();
}
@@ -529,19 +537,19 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
hr = pTaskFolder->DeleteTask(taskName, 0);
if (FAILED(hr))
{
- WcaLogError(hr, "Cannot delete the '%S' task: %x", taskName, hr);
+ Logger::error(L"Cannot delete the {} task: {}", taskName, hr);
}
SysFreeString(taskName);
}
else
{
- WcaLogError(hr, "Cannot get the registered task name: %x", hr);
+ Logger::error(L"Cannot get the registered task name: {}", hr);
}
pRegisteredTask->Release();
}
else
{
- WcaLogError(hr, "Cannot get the registered task item at index=%d: %x", i + 1, hr);
+ Logger::error(L"Cannot get the registered task item at index={}: {}", i + 1, hr);
}
}
@@ -553,7 +561,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
pRootFolder->Release();
ExitOnFailure(hr, "Cannot delete the PowerToys folder: %x", hr);
- WcaLog(LOGMSG_STANDARD, "Deleted the PowerToys Task Scheduler folder.");
+ Logger::info(L"Deleted the PowerToys Task Scheduler folder.");
LExit:
if (pService)
@@ -754,9 +762,13 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "DetectPrevInstallPathCA");
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", L"");
+
+ LPWSTR currentScope = nullptr;
+ hr = WcaGetProperty(L"InstallScope", ¤tScope);
+
try
{
- if (auto install_path = GetMsiPackageInstalledPath())
+ if (auto install_path = GetMsiPackageInstalledPath(std::wstring{ currentScope } == L"perUser"))
{
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", install_path->data());
}
@@ -809,7 +821,7 @@ UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
ExitOnFailure(hr, "Certificate file size not valid", hr);
}
- pFileContent = (char*)malloc(size);
+ pFileContent = static_cast(malloc(size));
DWORD sizeread;
if (!ReadFile(hfile, pFileContent, size, &sizeread, nullptr))
@@ -820,7 +832,7 @@ UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
if (!CertAddEncodedCertificateToStore(hCertStore,
X509_ASN_ENCODING,
- (const BYTE*)pFileContent,
+ reinterpret_cast(pFileContent),
size,
CERT_STORE_ADD_ALWAYS,
nullptr))
@@ -1004,6 +1016,7 @@ const std::wstring WinAppSDKConsumers[] =
L"modules\\MeasureTool",
L"modules\\FileLocksmith",
L"modules\\Hosts",
+ L"modules\\RegistryPreview",
L"modules\\Peek",
};
@@ -1058,6 +1071,8 @@ const std::wstring PTInteropConsumers[] =
L"modules\\Hosts",
L"modules\\Peek",
L"modules\\FileExplorerPreview",
+ L"modules\\MouseUtils\\MouseJumpUI",
+ L"modules\\RegistryPreview",
};
UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
@@ -1101,7 +1116,8 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder, dotnetRuntimeFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
- imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir, hostsDir, fileLocksmithDir, peekDir;
+ imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir, hostsDir, fileLocksmithDir,
+ mouseJumpDir, registryPreviewDir, peekDir;
hr = WcaInitialize(hInstall, "CreateDotnetRuntimeHardlinksCA");
ExitOnFailure(hr, "Failed to initialize");
@@ -1122,6 +1138,8 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
fileExplorerAddOnsDir = installationFolder + L"modules\\FileExplorerPreview\\";
hostsDir = installationFolder + L"modules\\Hosts\\";
fileLocksmithDir = installationFolder + L"modules\\FileLocksmith\\";
+ mouseJumpDir = installationFolder + L"modules\\MouseUtils\\MouseJumpUI\\";
+ registryPreviewDir = installationFolder + L"modules\\RegistryPreview\\";
peekDir = installationFolder + L"modules\\Peek\\";
for (auto file : dotnetRuntimeFiles)
@@ -1139,6 +1157,8 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileExplorerAddOnsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (hostsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileLocksmithDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (mouseJumpDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (registryPreviewDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (peekDir + file).c_str(), ec);
if (ec.value() != S_OK)
@@ -1163,6 +1183,8 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (powerAccentDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileExplorerAddOnsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (hostsDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (mouseJumpDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (registryPreviewDir + file).c_str(), ec);
if (ec.value() != S_OK)
{
@@ -1256,8 +1278,8 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
- imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir, peekDir,
- hostsDir, fileLocksmithDir;
+ imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir,
+ hostsDir, fileLocksmithDir, mouseJumpDir, registryPreviewDir, peekDir;
hr = WcaInitialize(hInstall, "DeleteDotnetRuntimeHardlinksCA");
ExitOnFailure(hr, "Failed to initialize");
@@ -1277,6 +1299,8 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
fileExplorerAddOnsDir = installationFolder + L"modules\\FileExplorerPreview\\";
hostsDir = installationFolder + L"modules\\Hosts\\";
fileLocksmithDir = installationFolder + L"modules\\FileLocksmith\\";
+ mouseJumpDir = installationFolder + L"modules\\MouseUtils\\MouseJumpUI\\";
+ registryPreviewDir = installationFolder + L"modules\\RegistryPreview\\";
peekDir = installationFolder + L"modules\\Peek\\";
try
@@ -1295,6 +1319,8 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
DeleteFile((fileExplorerAddOnsDir + file).c_str());
DeleteFile((hostsDir + file).c_str());
DeleteFile((fileLocksmithDir + file).c_str());
+ DeleteFile((mouseJumpDir + file).c_str());
+ DeleteFile((registryPreviewDir + file).c_str());
DeleteFile((peekDir + file).c_str());
}
@@ -1309,6 +1335,8 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
DeleteFile((powerAccentDir + file).c_str());
DeleteFile((fileExplorerAddOnsDir + file).c_str());
DeleteFile((hostsDir + file).c_str());
+ DeleteFile((mouseJumpDir + file).c_str());
+ DeleteFile((registryPreviewDir + file).c_str());
}
}
catch (std::exception e)
@@ -1342,17 +1370,19 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
}
processes.resize(bytes / sizeof(processes[0]));
- std::array processesToTerminate = {
+ std::array processesToTerminate = {
L"PowerToys.PowerLauncher.exe",
L"PowerToys.Settings.exe",
L"PowerToys.Awake.exe",
L"PowerToys.FancyZones.exe",
L"PowerToys.FancyZonesEditor.exe",
L"PowerToys.FileLocksmithUI.exe",
+ L"PowerToys.MouseJumpUI.exe",
L"PowerToys.ColorPickerUI.exe",
L"PowerToys.AlwaysOnTop.exe",
+ L"PowerToys.exe",
+ L"PowerToys.RegistryPreview.exe",
L"PowerToys.Peek.UI.exe",
- L"PowerToys.exe"
};
for (const auto procID : processes)
@@ -1407,6 +1437,20 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
return WcaFinalize(er);
}
+void initSystemLogger()
+{
+ static std::once_flag initLoggerFlag;
+ std::call_once(initLoggerFlag, []() {
+ WCHAR temp_path[MAX_PATH];
+ auto ret = GetTempPath(MAX_PATH, temp_path);
+
+ if (ret)
+ {
+ Logger::init("PowerToysMSI", std::wstring{ temp_path } + L"\\PowerToysMSIInstaller", L"");
+ }
+ });
+}
+
// DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
{
@@ -1414,6 +1458,7 @@ extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in L
{
case DLL_PROCESS_ATTACH:
WcaGlobalInitialize(hInst);
+ initSystemLogger();
TraceLoggingRegister(g_hProvider);
DLL_HANDLE = hInst;
break;
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def
index 27d59b2fda..21f2547052 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.def
+++ b/installer/PowerToysSetupCustomActions/CustomAction.def
@@ -1,6 +1,7 @@
LIBRARY "PowerToysSetupCustomActions"
EXPORTS
+ CheckGPOCA
ApplyModulesRegistryChangeSetsCA
CreateScheduledTaskCA
CreateWinAppSDKHardlinksCA
diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
index 07b2a3a065..f7370d499d 100644
--- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
+++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
@@ -1,4 +1,4 @@
-
+
@@ -33,8 +33,10 @@
- $(Platform)\$(Configuration)\
- $(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\obj\
+ $(Platform)\$(Configuration)\MachineSetup
+ $(Platform)\$(Configuration)\UserSetup
+ $(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\MachineSetup\obj\
+ $(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\UserSetup\obj\
true
@@ -47,8 +49,33 @@
call cmd /C "copy ""$(ProjectDir)DepsFilesLists.h"" ""$(ProjectDir)DepsFilesLists.h.bk"""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\AlwaysOnTop.wxs"" ""$(ProjectDir)..\PowerToysSetup\AlwaysOnTop.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Awake.wxs"" ""$(ProjectDir)..\PowerToysSetup\Awake.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs"" ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Core.wxs"" ""$(ProjectDir)..\PowerToysSetup\Core.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\FancyZones.wxs"" ""$(ProjectDir)..\PowerToysSetup\FancyZones.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\FileExplorerPreview.wxs"" ""$(ProjectDir)..\PowerToysSetup\FileExplorerPreview.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\FileLocksmith.wxs"" ""$(ProjectDir)..\PowerToysSetup\FileLocksmith.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Hosts.wxs"" ""$(ProjectDir)..\PowerToysSetup\Hosts.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ImageResizer.wxs"" ""$(ProjectDir)..\PowerToysSetup\ImageResizer.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\KeyboardManager.wxs"" ""$(ProjectDir)..\PowerToysSetup\KeyboardManager.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\MeasureTool.wxs"" ""$(ProjectDir)..\PowerToysSetup\MeasureTool.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\MouseUtils.wxs"" ""$(ProjectDir)..\PowerToysSetup\MouseUtils.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\PowerAccent.wxs"" ""$(ProjectDir)..\PowerToysSetup\PowerAccent.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\PowerRename.wxs"" ""$(ProjectDir)..\PowerToysSetup\PowerRename.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Product.wxs"" ""$(ProjectDir)..\PowerToysSetup\Product.wxs.bk""""
- call powershell.exe -File parseRuntimes.ps1 -depsjsonpath "$(ProjectDir)..\..\$(Platform)\$(Configuration)\modules\ColorPicker\PowerToys.ColorPickerUI.deps.json" -depsfileslistspath "$(ProjectDir)DepsFilesLists.h" -productwxspath "$(ProjectDir)..\PowerToysSetup\Product.wxs"
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\RegistryPreview.wxs"" ""$(ProjectDir)..\PowerToysSetup\RegistryPreview.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Resources.wxs"" ""$(ProjectDir)..\PowerToysSetup\Resources.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Run.wxs"" ""$(ProjectDir)..\PowerToysSetup\Run.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Settings.wxs"" ""$(ProjectDir)..\PowerToysSetup\Settings.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ShortcutGuide.wxs"" ""$(ProjectDir)..\PowerToysSetup\ShortcutGuide.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\TextExtractor.wxs"" ""$(ProjectDir)..\PowerToysSetup\TextExtractor.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Tools.wxs"" ""$(ProjectDir)..\PowerToysSetup\Tools.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs"" ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs.bk""""
+ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs"" ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs.bk""""
+ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File parseRuntimes.ps1 -runtimedepsjsonpath "$(ProjectDir)..\..\$(Platform)\$(Configuration)\Settings\PowerToys.Settings.deps.json" -wpfdepsjsonpath "$(ProjectDir)..\..\$(Platform)\$(Configuration)\modules\ColorPicker\PowerToys.ColorPickerUI.deps.json" -depsfileslistspath "$(ProjectDir)DepsFilesLists.h" -productwxspath "$(ProjectDir)..\PowerToysSetup\Core.wxs"
+ if not "$(PerUser)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetup\generateAllFileComponents.ps1 -platform $(Platform)
+ if "$(PerUser)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetup\generateAllFileComponents.ps1 -platform $(Platform) -installscopeperuser $(PerUser)
Backing up original files and populating .NET and WPF Runtime dependencies
diff --git a/installer/PowerToysSetupCustomActions/parseRuntimes.ps1 b/installer/PowerToysSetupCustomActions/parseRuntimes.ps1
index f031c4429d..1ea58c268c 100644
--- a/installer/PowerToysSetupCustomActions/parseRuntimes.ps1
+++ b/installer/PowerToysSetupCustomActions/parseRuntimes.ps1
@@ -1,13 +1,46 @@
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True, Position = 1)]
- [string]$depsjsonpath,
+ [string]$runtimedepsjsonpath,
[Parameter(Mandatory = $True, Position = 2)]
- [string]$depsfileslistspath,
+ [string]$wpfdepsjsonpath,
[Parameter(Mandatory = $True, Position = 3)]
+ [string]$depsfileslistspath,
+ [Parameter(Mandatory = $True, Position = 4)]
[string]$productwxspath
)
+function Get-RuntimePack ($depsJsonFile, $runtimeName) {
+ Write-Host "Parsing $runtimeName Runtime"
+ $runtimePackList = ([array]$depsJsonFile.targets.PSObject.Properties)[-1].Value.PSObject.Properties | Where-Object { $_.Name -match "runtimepack.$runtimeName" };
+
+ if ($runtimePackList.Length -eq 0) {
+ Write-Host -ForegroundColor Red "$runtimeName has not been found"
+ exit 1
+ }
+
+ # Enumerate through array of custom objects and parse the names of the property values into a HashTable
+ $runtimePackList | ForEach-Object {
+ $runtimes += @{"$($_.Name -replace "runtimepack\.(\S+)\.\S+/\S+",'$1')" = $_.Value.PSObject.Properties.Value | ForEach-Object {
+ $_.PSObject.Properties.Name
+ }
+ }
+ }
+ Write-Output $runtimes;
+}
+
+function Update-RuntimeHashTable () {
+ $runtimes = Get-RuntimePack $runtimeFile "Microsoft.NETCore.App.Runtime"
+ $runtimes = Get-RuntimePack $wpfRuntimeFile "Microsoft.WindowsDesktop.App.Runtime"
+
+ # Find the dlls that exist in both the .NET Runtime and WPF Runtime deps list and filter out of WPF
+ $runtimeFileComparison = Compare-Object -ReferenceObject $runtimes["Microsoft.NETCore.App.Runtime"] -DifferenceObject $runtimes["Microsoft.WindowsDesktop.App.Runtime"] -IncludeEqual -ExcludeDifferent
+
+ $runtimes["Microsoft.WindowsDesktop.App.Runtime"] = $runtimes["Microsoft.WindowsDesktop.App.Runtime"] | Where-Object { $_ -notin $runtimeFileComparison.InputObject }
+
+ Write-Output $runtimes;
+}
+
function Update-RuntimeFileList($runtimeToken, $runtimeKey) {
$depsFilesLists -replace "($runtimeToken = )(.*);", "`$1 {`r`n$(($runtimes[$runtimeKey] | ForEach-Object {' L"'+$_+'"'} | Sort-Object) -join ",`r`n") };"
}
@@ -16,8 +49,7 @@ function Update-ProductWxsRuntimeFileList($runtimeToken, $runtimeKey) {
$productWxs -replace "(define $runtimeToken=)(.*)?>", "`$1$($runtimes[$runtimeKey] -join ';')?>"
}
-function Update-DotnetFilesComponentGuid()
-{
+function Update-DotnetFilesComponentGuid() {
$productWxs -replace "Dlls_DotnetFiles_Component"" Guid=""([{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?)""", "Dlls_DotnetFiles_Component"" Guid=""$((New-Guid).ToString().ToUpper())"""
}
@@ -28,26 +60,12 @@ $depsFilesLists = Get-Content $depsfileslistspath;
$productWxs = Get-Content $productwxspath;
# Read the deps.json file and convert it to a JSON object
-$runtimeFile = Get-Content $depsjsonpath | ConvertFrom-Json;
+$runtimeFile = Get-Content $runtimedepsjsonpath | ConvertFrom-Json;
+$wpfRuntimeFile = Get-Content $wpfdepsjsonpath | ConvertFrom-Json;
$runtimes = @{}
-Write-Host "Parsing .NET Runtimes from $depsjsonpath `r`n"
-
-$runtimeList = ([array]$runtimeFile.targets.PSObject.Properties)[-1].Value.PSObject.Properties | Where-Object { $_.Name -match "runtimepack" };
-
-if ($runtimeList.Length -eq 0) {
- Write-Host -ForegroundColor Red "No runtimes have been detected"
- exit 1
-}
-
-# Enumerate through array of custom objects and parse the names of the property values into a HashTable
-$runtimeList | ForEach-Object {
- $runtimes += @{"$($_.Name -replace "runtimepack\.(\S+)\.\S+/\S+",'$1')" = $_.Value.PSObject.Properties.Value | ForEach-Object {
- $_.PSObject.Properties.Name
- }
- }
-}
+$runtimes = Update-RuntimeHashTable
Write-Host "Writing Microsoft.NETCore.App.Runtime files"
$depsFilesLists = Update-RuntimeFileList "dotnetRuntimeFiles" "Microsoft.NETCore.App.Runtime"
@@ -64,6 +82,4 @@ Write-Host "Updating $depsfileslistspath"
Set-Content -Path $depsfileslistspath -Value $depsFilesLists
Write-Host "Updating $productwxspath"
-Set-Content -Path $productwxspath -Value $productWxs
-
-
+Set-Content -Path $productwxspath -Value $productWxs
\ No newline at end of file
diff --git a/nuget.config b/nuget.config
index 5a4b9c0fb9..81243afb3c 100644
--- a/nuget.config
+++ b/nuget.config
@@ -1,5 +1,13 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Update/PowerToys.Update.cpp b/src/Update/PowerToys.Update.cpp
index 31e4eb8143..d19647623d 100644
--- a/src/Update/PowerToys.Update.cpp
+++ b/src/Update/PowerToys.Update.cpp
@@ -110,7 +110,7 @@ bool InstallNewVersionStage1(fs::path installer)
{
// Detect if PT was running
const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr);
- const bool launch_powertoys = pt_main_window != nullptr;
+
if (pt_main_window != nullptr)
{
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
@@ -119,10 +119,7 @@ bool InstallNewVersionStage1(fs::path installer)
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
arguments += L" \"";
arguments += installer.c_str();
- arguments += L"\" \"";
- arguments += get_module_folderpath();
- arguments += L"\" ";
- arguments += launch_powertoys ? UPDATE_STAGE2_RESTART_PT : UPDATE_STAGE2_DONT_START_PT;
+ arguments += L"\"";
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
sei.lpFile = copy_in_temp->c_str();
@@ -137,7 +134,7 @@ bool InstallNewVersionStage1(fs::path installer)
}
}
-bool InstallNewVersionStage2(std::wstring installer_path, std::wstring_view install_path, bool launch_powertoys)
+bool InstallNewVersionStage2(std::wstring installer_path)
{
std::transform(begin(installer_path), end(installer_path), begin(installer_path), ::towlower);
@@ -181,18 +178,6 @@ bool InstallNewVersionStage2(std::wstring installer_path, std::wstring_view inst
state.state = UpdateState::upToDate;
});
- if (launch_powertoys)
- {
- std::wstring new_pt_path{ install_path };
- new_pt_path += L"\\PowerToys.exe";
- SHELLEXECUTEINFOW sei{ sizeof(sei) };
- sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
- sei.lpFile = new_pt_path.c_str();
- sei.nShow = SW_SHOWNORMAL;
- sei.lpParameters = UPDATE_REPORT_SUCCESS;
- return ShellExecuteExW(&sei) == TRUE;
- }
-
return true;
}
@@ -230,7 +215,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
{
using namespace std::string_view_literals;
- const bool failed = !InstallNewVersionStage2(args[2], args[3], args[4] == std::wstring_view{ UPDATE_STAGE2_RESTART_PT });
+ const bool failed = !InstallNewVersionStage2(args[2]);
if (failed)
{
UpdateState::store([&](UpdateState& state) {
diff --git a/src/common/AllExperiments/AllExperiments.csproj b/src/common/AllExperiments/AllExperiments.csproj
new file mode 100644
index 0000000000..44b823cbbc
--- /dev/null
+++ b/src/common/AllExperiments/AllExperiments.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net7.0-windows10.0.19041.0
+ enable
+ enable
+ PowerToys.AllExperiments
+ .\Microsoft.VariantAssignment\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/common/AllExperiments/Experiments.cs b/src/common/AllExperiments/Experiments.cs
new file mode 100644
index 0000000000..38ac694637
--- /dev/null
+++ b/src/common/AllExperiments/Experiments.cs
@@ -0,0 +1,212 @@
+// 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.Globalization;
+using System.Text.Json;
+using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
+using Microsoft.PowerToys.Telemetry;
+using Microsoft.VariantAssignment.Client;
+using Microsoft.VariantAssignment.Contract;
+using Windows.System.Profile;
+
+namespace AllExperiments
+{
+ // The dependencies required to build this project are only available in the official build pipeline and are internal to Microsoft.
+ // However, this project is not required to build a test version of the application.
+ public class Experiments
+ {
+ public enum ExperimentState
+ {
+ Enabled,
+ Disabled,
+ NotLoaded,
+ }
+
+#pragma warning disable SA1401 // Need to use LandingPageExperiment as a static property in OobeShellPage.xaml.cs
+#pragma warning disable CA2211 // Non-constant fields should not be visible
+ public static ExperimentState LandingPageExperiment = ExperimentState.NotLoaded;
+#pragma warning restore CA2211
+#pragma warning restore SA1401
+
+ public async Task EnableLandingPageExperimentAsync()
+ {
+ if (Experiments.LandingPageExperiment != ExperimentState.NotLoaded)
+ {
+ return Experiments.LandingPageExperiment == ExperimentState.Enabled;
+ }
+
+ Experiments varServ = new Experiments();
+ await varServ.VariantAssignmentProvider_Initialize();
+ var landingPageExperiment = varServ.IsExperiment;
+
+ Experiments.LandingPageExperiment = landingPageExperiment ? ExperimentState.Enabled : ExperimentState.Disabled;
+
+ return landingPageExperiment;
+ }
+
+ private async Task VariantAssignmentProvider_Initialize()
+ {
+ IsExperiment = false;
+ string jsonFilePath = CreateFilePath();
+
+ var vaSettings = new VariantAssignmentClientSettings
+ {
+ Endpoint = new Uri("https://default.exp-tas.com/exptas77/a7a397e7-6fbe-4f21-a4e9-3f542e4b000e-exppowertoys/api/v1/tas"),
+ EnableCaching = true,
+ ResponseCacheTime = TimeSpan.FromMinutes(5),
+ };
+
+ try
+ {
+ var vaClient = vaSettings.GetTreatmentAssignmentServiceClient();
+ var vaRequest = GetVariantAssignmentRequest();
+ using var variantAssignments = await vaClient.GetVariantAssignmentsAsync(vaRequest).ConfigureAwait(false);
+
+ if (variantAssignments.AssignedVariants.Count != 0)
+ {
+ var dataVersion = variantAssignments.DataVersion;
+ var featureVariables = variantAssignments.GetFeatureVariables();
+ var assignmentContext = variantAssignments.GetAssignmentContext();
+ var featureFlagValue = featureVariables[0].GetStringValue();
+
+ var experimentGroup = string.Empty;
+ string json = File.ReadAllText(jsonFilePath);
+ var jsonDictionary = JsonSerializer.Deserialize>(json);
+
+ if (jsonDictionary != null)
+ {
+ if (!jsonDictionary.ContainsKey("dataversion"))
+ {
+ jsonDictionary.Add("dataversion", dataVersion);
+ }
+
+ if (!jsonDictionary.ContainsKey("variantassignment"))
+ {
+ jsonDictionary.Add("variantassignment", featureFlagValue);
+ }
+ else
+ {
+ var jsonDataVersion = jsonDictionary["dataversion"].ToString();
+ if (jsonDataVersion != null && int.Parse(jsonDataVersion, CultureInfo.InvariantCulture) < dataVersion)
+ {
+ jsonDictionary["dataversion"] = dataVersion;
+ jsonDictionary["variantassignment"] = featureFlagValue;
+ }
+ }
+
+ experimentGroup = jsonDictionary["variantassignment"].ToString();
+
+ string output = JsonSerializer.Serialize(jsonDictionary);
+ File.WriteAllText(jsonFilePath, output);
+ }
+
+ if (experimentGroup == "alternate" && AssignmentUnit != string.Empty)
+ {
+ IsExperiment = true;
+ }
+
+ PowerToysTelemetry.Log.WriteEvent(new OobeVariantAssignmentEvent() { AssignmentContext = assignmentContext, ClientID = AssignmentUnit });
+ }
+ }
+ catch (HttpRequestException ex)
+ {
+ string json = File.ReadAllText(jsonFilePath);
+ var jsonDictionary = JsonSerializer.Deserialize>(json);
+
+ if (jsonDictionary != null)
+ {
+ if (jsonDictionary.ContainsKey("variantassignment"))
+ {
+ if (jsonDictionary["variantassignment"].ToString() == "alternate" && AssignmentUnit != string.Empty)
+ {
+ IsExperiment = true;
+ }
+ }
+ else
+ {
+ jsonDictionary["variantassignment"] = "current";
+ }
+ }
+
+ string output = JsonSerializer.Serialize(jsonDictionary);
+ File.WriteAllText(jsonFilePath, output);
+
+ Logger.LogError("Error getting to TAS endpoint", ex);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError("Error getting variant assignments for experiment", ex);
+ }
+ }
+
+ public bool IsExperiment { get; set; }
+
+ private string? AssignmentUnit { get; set; }
+
+ private IVariantAssignmentRequest GetVariantAssignmentRequest()
+ {
+ var jsonFilePath = CreateFilePath();
+ try
+ {
+ if (!File.Exists(jsonFilePath))
+ {
+ AssignmentUnit = Guid.NewGuid().ToString();
+ var data = new Dictionary()
+ {
+ ["clientid"] = AssignmentUnit,
+ };
+ string jsonData = JsonSerializer.Serialize(data);
+ File.WriteAllText(jsonFilePath, jsonData);
+ }
+ else
+ {
+ string json = File.ReadAllText(jsonFilePath);
+ var jsonDictionary = System.Text.Json.JsonSerializer.Deserialize>(json);
+ if (jsonDictionary != null)
+ {
+ AssignmentUnit = jsonDictionary["clientid"]?.ToString();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError("Error creating/getting AssignmentUnit", ex);
+ }
+
+ var attrNames = new List { "FlightRing", "c:InstallLanguage" };
+ var attrData = AnalyticsInfo.GetSystemPropertiesAsync(attrNames).AsTask().GetAwaiter().GetResult();
+
+ var flightRing = string.Empty;
+ var installLanguage = string.Empty;
+
+ if (attrData.ContainsKey("FlightRing"))
+ {
+ flightRing = attrData["FlightRing"];
+ }
+
+ if (attrData.ContainsKey("InstallLanguage"))
+ {
+ installLanguage = attrData["InstallLanguage"];
+ }
+
+ return new VariantAssignmentRequest
+ {
+ Parameters =
+ {
+ { "installLanguage", installLanguage },
+ { "flightRing", flightRing },
+ { "clientid", AssignmentUnit },
+ },
+ };
+ }
+
+ private string CreateFilePath()
+ {
+ var exeDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ var settingsPath = @"Microsoft\PowerToys\experimentation.json";
+ var filePath = Path.Combine(exeDir, settingsPath);
+ return filePath;
+ }
+ }
+}
diff --git a/src/settings-ui/Settings.UI.Library/Utilities/Logger.cs b/src/common/AllExperiments/Logger.cs
similarity index 93%
rename from src/settings-ui/Settings.UI.Library/Utilities/Logger.cs
rename to src/common/AllExperiments/Logger.cs
index fbac2c88fb..7604618bdf 100644
--- a/src/settings-ui/Settings.UI.Library/Utilities/Logger.cs
+++ b/src/common/AllExperiments/Logger.cs
@@ -7,7 +7,7 @@ using System.Diagnostics;
using System.Globalization;
using System.IO.Abstractions;
-namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
+namespace AllExperiments
{
public static class Logger
{
@@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
private static readonly IPath Path = FileSystem.Path;
private static readonly IDirectory Directory = FileSystem.Directory;
- private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\Settings Logs");
+ private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\Settings Logs\\Experimentation");
static Logger()
{
@@ -74,7 +74,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
StackTrace stackTrace = new StackTrace();
var methodName = stackTrace.GetFrame(3)?.GetMethod();
- var className = methodName?.DeclaringType.Name;
+ var className = methodName?.DeclaringType?.Name;
return "[Method]: " + methodName?.Name + " [Class]: " + className;
}
}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentClientExtensionMethods.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentClientExtensionMethods.cs
new file mode 100644
index 0000000000..ee08acd718
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentClientExtensionMethods.cs
@@ -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 Microsoft.VariantAssignment.Contract;
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Client
+{
+#pragma warning disable SA1200 // Using directives should be placed correctly
+ using TreatmentAssignmentServiceClient = VariantAssignmentServiceClient;
+#pragma warning restore SA1200 // Using directives should be placed correctly
+
+ public static class VariantAssignmentClientExtensionMethods
+ {
+ public static IVariantAssignmentProvider GetTreatmentAssignmentServiceClient(this VariantAssignmentClientSettings settings)
+ {
+ return new TreatmentAssignmentServiceClient();
+ }
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentServiceClient.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentServiceClient.cs
new file mode 100644
index 0000000000..373651f83a
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Client/VariantAssignmentServiceClient.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.VariantAssignment.Contract;
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Client
+{
+ internal sealed partial class VariantAssignmentServiceClient : IVariantAssignmentProvider, IDisposable
+ where TServerResponse : VariantAssignmentServiceResponse
+ {
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task GetVariantAssignmentsAsync(IVariantAssignmentRequest request, CancellationToken ct = default)
+ {
+ return Task.FromResult(EmptyVariantAssignmentResponse.Instance);
+ }
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/EmptyVariantAssignmentResponse.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/EmptyVariantAssignmentResponse.cs
new file mode 100644
index 0000000000..0e0cd54094
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/EmptyVariantAssignmentResponse.cs
@@ -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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public class EmptyVariantAssignmentResponse : IVariantAssignmentResponse
+ {
+ ///
+ /// Singleton instance of .
+ ///
+ public static readonly IVariantAssignmentResponse Instance = new EmptyVariantAssignmentResponse();
+
+ public EmptyVariantAssignmentResponse()
+ {
+ }
+
+ public long DataVersion => 0;
+
+ public string Thumbprint => string.Empty;
+
+ ///
+ public IReadOnlyCollection AssignedVariants => Array.Empty();
+
+ ///
+#pragma warning disable CS8603 // Possible null reference return.
+ public IFeatureVariable GetFeatureVariable(IReadOnlyList path) => null;
+#pragma warning restore CS8603 // Possible null reference return.
+
+ ///
+ public IReadOnlyList GetFeatureVariables(IReadOnlyList prefix) => Array.Empty();
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+ string IVariantAssignmentResponse.GetAssignmentContext()
+ {
+ throw new NotImplementedException();
+ }
+
+ IReadOnlyList IVariantAssignmentResponse.GetFeatureVariables()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IAssignedVariant.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IAssignedVariant.cs
new file mode 100644
index 0000000000..6c9a31e8ce
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IAssignedVariant.cs
@@ -0,0 +1,11 @@
+// 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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public interface IAssignedVariant
+ {
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IFeatureVariable.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IFeatureVariable.cs
new file mode 100644
index 0000000000..fc9193ed0d
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IFeatureVariable.cs
@@ -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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public interface IFeatureVariable
+ {
+ ///
+ /// Gets the variable's value as a string.
+ ///
+ /// String value of the variable.
+ string GetStringValue();
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentProvider.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentProvider.cs
new file mode 100644
index 0000000000..dad9d39038
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentProvider.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public interface IVariantAssignmentProvider : IDisposable
+ {
+ ///
+ /// Computes variant assignments based on data.
+ ///
+ /// Variant assignment parameters.
+ /// Propagates notification that operations should be canceled.
+ /// An awaitable task that returns a .
+ Task GetVariantAssignmentsAsync(IVariantAssignmentRequest request, CancellationToken ct = default);
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentRequest.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentRequest.cs
new file mode 100644
index 0000000000..9639a3a58d
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentRequest.cs
@@ -0,0 +1,15 @@
+// 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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public interface IVariantAssignmentRequest
+ {
+ ///
+ /// Gets inputs used for evaluating filters, assignment units, etc.
+ ///
+ IReadOnlyCollection<(string Key, string Value)> Parameters { get; }
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentResponse.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentResponse.cs
new file mode 100644
index 0000000000..29ee2209de
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/IVariantAssignmentResponse.cs
@@ -0,0 +1,48 @@
+// 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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ ///
+ /// Snapshot of variant assignments.
+ ///
+ public interface IVariantAssignmentResponse : IDisposable
+ {
+ /////
+ ///// Gets the serial number of variant assignment configuration snapshot used when assigning variants.
+ /////
+ long DataVersion { get; }
+
+ /////
+ ///// Get a hash of the response suitable for caching.
+ /////
+ // string Thumbprint { get; }
+
+ ///
+ /// Gets the variants assigned based on request parameters and a variant configuration snapshot.
+ ///
+ IReadOnlyCollection AssignedVariants { get; }
+
+ ///
+ /// Gets feature variables assigned by variants in this response.
+ ///
+ /// (Optional) Filter feature variables where contains the .
+ /// Range of matching feature variables.
+ IReadOnlyList GetFeatureVariables(IReadOnlyList prefix);
+
+ // this actually part of the interface but gets the job done
+ IReadOnlyList GetFeatureVariables();
+
+ // this actually part of the interface but gets the job done
+ string GetAssignmentContext();
+
+ ///
+ /// Gets a single feature variable assigned by variants in this response.
+ ///
+ /// Exact feature variable path.
+ /// Matching feature variable or null.
+ IFeatureVariable GetFeatureVariable(IReadOnlyList path);
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/TreatmentAssignmentServiceResponse.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/TreatmentAssignmentServiceResponse.cs
new file mode 100644
index 0000000000..6db91f6ffd
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/TreatmentAssignmentServiceResponse.cs
@@ -0,0 +1,11 @@
+// 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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ internal sealed class TreatmentAssignmentServiceResponse : VariantAssignmentServiceResponse
+ {
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentClientSettings.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentClientSettings.cs
new file mode 100644
index 0000000000..1ea295bfda
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentClientSettings.cs
@@ -0,0 +1,31 @@
+// 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.ComponentModel.DataAnnotations;
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ ///
+ /// Configuration for variant assignment service client.
+ ///
+ public class VariantAssignmentClientSettings
+ {
+ ///
+ /// Gets or sets the variant assignment service endpoint URL.
+ ///
+ [Required]
+ public Uri? Endpoint { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether gets or sets a value whether client side request caching should be enabled.
+ ///
+ public bool EnableCaching { get; set; }
+
+ ///
+ /// Gets or sets the the maximum time a cached variant assignment response may be used without re-validating.
+ ///
+ public TimeSpan ResponseCacheTime { get; set; }
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentRequest.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentRequest.cs
new file mode 100644
index 0000000000..976ce53531
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentRequest.cs
@@ -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.Collections.Specialized;
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ public class VariantAssignmentRequest : IVariantAssignmentRequest
+ {
+ private NameValueCollection _parameters = new NameValueCollection();
+
+ ///
+ /// Gets or sets mutable .
+ ///
+ public NameValueCollection Parameters { get => _parameters; set => _parameters = value; }
+
+ IReadOnlyCollection<(string Key, string Value)> IVariantAssignmentRequest.Parameters => (IReadOnlyCollection<(string Key, string Value)>)_parameters;
+ }
+}
diff --git a/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentServiceResponse.cs b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentServiceResponse.cs
new file mode 100644
index 0000000000..e87425f4d3
--- /dev/null
+++ b/src/common/AllExperiments/Microsoft.VariantAssignment/Contract/VariantAssignmentServiceResponse.cs
@@ -0,0 +1,48 @@
+// 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.
+
+// The goal of this class is to just mock out the Microsoft.VariantAssignment close source objects
+namespace Microsoft.VariantAssignment.Contract
+{
+ ///
+ /// Mutable implementation of for (de)serialization.
+ ///
+ internal class VariantAssignmentServiceResponse : IVariantAssignmentResponse, IDisposable
+ {
+ ///
+ public virtual long DataVersion { get; set; }
+
+ public virtual IReadOnlyCollection AssignedVariants { get; set; } = Array.Empty();
+
+ public IFeatureVariable GetFeatureVariable(IReadOnlyList path)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IReadOnlyList GetFeatureVariables(IReadOnlyList prefix)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public IReadOnlyList GetFeatureVariables()
+ {
+ throw new NotImplementedException();
+ }
+
+ public string GetAssignmentContext()
+ {
+ return string.Empty;
+ }
+ }
+}
diff --git a/src/common/Common.UI/Common.UI.csproj b/src/common/Common.UI/Common.UI.csproj
index 9175a0706c..a4475f640c 100644
--- a/src/common/Common.UI/Common.UI.csproj
+++ b/src/common/Common.UI/Common.UI.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/common/Common.UI/SettingsDeepLink.cs b/src/common/Common.UI/SettingsDeepLink.cs
index 42da58b8a0..c63f3fc1ad 100644
--- a/src/common/Common.UI/SettingsDeepLink.cs
+++ b/src/common/Common.UI/SettingsDeepLink.cs
@@ -24,6 +24,7 @@ namespace Common.UI
ShortcutGuide,
VideoConference,
Hosts,
+ RegistryPreview,
}
private static string SettingsWindowNameToString(SettingsWindow value)
@@ -56,6 +57,8 @@ namespace Common.UI
return "VideoConference";
case SettingsWindow.Hosts:
return "Hosts";
+ case SettingsWindow.RegistryPreview:
+ return "RegistryPreview";
default:
{
return string.Empty;
diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp
index 513ba8a5c1..9e4a6ef347 100644
--- a/src/common/GPOWrapper/GPOWrapper.cpp
+++ b/src/common/GPOWrapper/GPOWrapper.cpp
@@ -6,110 +6,130 @@ namespace winrt::PowerToys::GPOWrapper::implementation
{
GpoRuleConfigured GPOWrapper::GetConfiguredAlwaysOnTopEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredAlwaysOnTopEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredAlwaysOnTopEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredAwakeEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredAwakeEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredAwakeEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredColorPickerEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredColorPickerEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredColorPickerEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredFancyZonesEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredFancyZonesEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredFancyZonesEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredFileLocksmithEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredFileLocksmithEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredFileLocksmithEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredSvgPreviewEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredSvgPreviewEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredSvgPreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredMarkdownPreviewEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredMarkdownPreviewEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredMarkdownPreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredMonacoPreviewEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredMonacoPreviewEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredMonacoPreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredPdfPreviewEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredPdfPreviewEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredPdfPreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredGcodePreviewEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredGcodePreviewEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredGcodePreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredSvgThumbnailsEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredSvgThumbnailsEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredSvgThumbnailsEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredPdfThumbnailsEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredPdfThumbnailsEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredPdfThumbnailsEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredGcodeThumbnailsEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredGcodeThumbnailsEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredGcodeThumbnailsEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredStlThumbnailsEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredStlThumbnailsEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredStlThumbnailsEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredHostsFileEditorEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredHostsFileEditorEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredHostsFileEditorEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredImageResizerEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredImageResizerEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredImageResizerEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredKeyboardManagerEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredKeyboardManagerEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredKeyboardManagerEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredFindMyMouseEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredFindMyMouseEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredFindMyMouseEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredMouseHighlighterEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredMouseHighlighterEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredMouseHighlighterEnabledValue());
+ }
+ GpoRuleConfigured GPOWrapper::GetConfiguredMouseJumpEnabledValue()
+ {
+ return static_cast(powertoys_gpo::getConfiguredMouseJumpEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredMousePointerCrosshairsEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredPowerRenameEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredPowerRenameEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredPowerRenameEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredPowerLauncherEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredPowerLauncherEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredPowerLauncherEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredQuickAccentEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredQuickAccentEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredQuickAccentEnabledValue());
+ }
+ GpoRuleConfigured GPOWrapper::GetConfiguredRegistryPreviewEnabledValue()
+ {
+ return static_cast(powertoys_gpo::getConfiguredRegistryPreviewEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredScreenRulerEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredScreenRulerEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredScreenRulerEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredShortcutGuideEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredShortcutGuideEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredShortcutGuideEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredTextExtractorEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredTextExtractorEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredTextExtractorEnabledValue());
+ }
+ GpoRuleConfigured GPOWrapper::GetConfiguredPastePlainEnabledValue()
+ {
+ return static_cast(powertoys_gpo::getConfiguredPastePlainEnabledValue());
}
GpoRuleConfigured GPOWrapper::GetConfiguredVideoConferenceMuteEnabledValue()
{
- return (GpoRuleConfigured)powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue();
+ return static_cast(powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue());
+ }
+ GpoRuleConfigured GPOWrapper::GetDisableAutomaticUpdateDownloadValue()
+ {
+ return static_cast(powertoys_gpo::getDisableAutomaticUpdateDownloadValue());
+ }
+ GpoRuleConfigured GPOWrapper::GetAllowExperimentationValue()
+ {
+ return static_cast(powertoys_gpo::getAllowExperimentationValue());
}
}
diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h
index 25b8d87445..77d6ba72f9 100644
--- a/src/common/GPOWrapper/GPOWrapper.h
+++ b/src/common/GPOWrapper/GPOWrapper.h
@@ -26,14 +26,19 @@ namespace winrt::PowerToys::GPOWrapper::implementation
static GpoRuleConfigured GetConfiguredKeyboardManagerEnabledValue();
static GpoRuleConfigured GetConfiguredFindMyMouseEnabledValue();
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
+ static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
static GpoRuleConfigured GetConfiguredQuickAccentEnabledValue();
+ static GpoRuleConfigured GetConfiguredRegistryPreviewEnabledValue();
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
+ static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
+ static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue();
+ static GpoRuleConfigured GetAllowExperimentationValue();
};
}
diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl
index f316b63fe1..b0f1633dfc 100644
--- a/src/common/GPOWrapper/GPOWrapper.idl
+++ b/src/common/GPOWrapper/GPOWrapper.idl
@@ -30,14 +30,19 @@ namespace PowerToys
static GpoRuleConfigured GetConfiguredKeyboardManagerEnabledValue();
static GpoRuleConfigured GetConfiguredFindMyMouseEnabledValue();
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
+ static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
static GpoRuleConfigured GetConfiguredQuickAccentEnabledValue();
+ static GpoRuleConfigured GetConfiguredRegistryPreviewEnabledValue();
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
+ static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
+ static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue();
+ static GpoRuleConfigured GetAllowExperimentationValue();
}
}
}
diff --git a/src/common/GPOWrapperProjection/GPOWrapper.cs b/src/common/GPOWrapperProjection/GPOWrapper.cs
index 7017a42084..108907d143 100644
--- a/src/common/GPOWrapperProjection/GPOWrapper.cs
+++ b/src/common/GPOWrapperProjection/GPOWrapper.cs
@@ -41,5 +41,10 @@ namespace PowerToys.GPOWrapperProjection
{
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredTextExtractorEnabledValue();
}
+
+ public static GpoRuleConfigured GetConfiguredPastePlainEnabledValue()
+ {
+ return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredPastePlainEnabledValue();
+ }
}
}
diff --git a/src/common/GPOWrapperProjection/GPOWrapperProjection.csproj b/src/common/GPOWrapperProjection/GPOWrapperProjection.csproj
index bd20c2a527..4cfc2521c6 100644
--- a/src/common/GPOWrapperProjection/GPOWrapperProjection.csproj
+++ b/src/common/GPOWrapperProjection/GPOWrapperProjection.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Logs/Logger.cs b/src/common/ManagedCommon/Logger.cs
similarity index 68%
rename from src/modules/fancyzones/editor/FancyZonesEditor/Logs/Logger.cs
rename to src/common/ManagedCommon/Logger.cs
index 1998ddd516..0d6cc32f2d 100644
--- a/src/modules/fancyzones/editor/FancyZonesEditor/Logs/Logger.cs
+++ b/src/common/ManagedCommon/Logger.cs
@@ -8,16 +8,16 @@ using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Reflection;
+using System.Runtime.Serialization;
using interop;
-namespace FancyZonesEditor.Logs
+namespace ManagedCommon
{
public static class Logger
{
private static readonly IFileSystem _fileSystem = new FileSystem();
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
- public static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion;
- private static readonly string ApplicationLogPath = Path.Combine(Constants.AppDataPath(), "FancyZones\\Editor\\Logs\\", Version);
+ private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion;
private static readonly string Error = "Error";
private static readonly string Warning = "Warning";
@@ -25,15 +25,29 @@ namespace FancyZonesEditor.Logs
private static readonly string Debug = "Debug";
private static readonly string TraceFlag = "Trace";
- static Logger()
+ ///
+ /// Initializes the logger and sets the path for logging.
+ ///
+ /// InitializeLogger("\\FancyZones\\Editor\\Logs")
+ /// The path to the log files folder.
+ /// If the process using Logger is a low-privilege process.
+ public static void InitializeLogger(string applicationLogPath, bool isLocalLow = false)
{
- if (!_fileSystem.Directory.Exists(ApplicationLogPath))
+ if (isLocalLow)
{
- _fileSystem.Directory.CreateDirectory(ApplicationLogPath);
+ applicationLogPath = Environment.GetEnvironmentVariable("userprofile") + "\\appdata\\LocalLow\\Microsoft\\PowerToys" + applicationLogPath + "\\" + Version;
+ }
+ else
+ {
+ applicationLogPath = Constants.AppDataPath() + applicationLogPath + "\\" + Version;
}
- // Using InvariantCulture since this is used for a log file name
- var logFilePath = _fileSystem.Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
+ if (!_fileSystem.Directory.Exists(applicationLogPath))
+ {
+ _fileSystem.Directory.CreateDirectory(applicationLogPath);
+ }
+
+ var logFilePath = _fileSystem.Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
@@ -91,7 +105,7 @@ namespace FancyZonesEditor.Logs
private static string GetCallerInfo()
{
- StackTrace stackTrace = new StackTrace();
+ StackTrace stackTrace = new();
var methodName = stackTrace.GetFrame(3)?.GetMethod();
var className = methodName?.DeclaringType.Name;
diff --git a/src/common/ManagedCommon/ManagedCommon.csproj b/src/common/ManagedCommon/ManagedCommon.csproj
index 18608ef4f8..05f9bd34e1 100644
--- a/src/common/ManagedCommon/ManagedCommon.csproj
+++ b/src/common/ManagedCommon/ManagedCommon.csproj
@@ -13,10 +13,12 @@
-
+
+
+
diff --git a/src/common/SettingsAPI/settings_objects.cpp b/src/common/SettingsAPI/settings_objects.cpp
index f7bd573845..6f3aa4c792 100644
--- a/src/common/SettingsAPI/settings_objects.cpp
+++ b/src/common/SettingsAPI/settings_objects.cpp
@@ -247,7 +247,7 @@ namespace PowerToysSettings
bool Settings::serialize_to_buffer(wchar_t* buffer, int* buffer_size)
{
auto result = m_json.Stringify();
- const int result_len = (int)result.size() + 1;
+ const int result_len = static_cast(result.size() + 1);
if (buffer == nullptr || *buffer_size < result_len)
{
diff --git a/src/common/SettingsAPI/settings_objects.h b/src/common/SettingsAPI/settings_objects.h
index cee95d7a56..1c84ac19b7 100644
--- a/src/common/SettingsAPI/settings_objects.h
+++ b/src/common/SettingsAPI/settings_objects.h
@@ -220,7 +220,7 @@ namespace PowerToysSettings
std::array key_states{}; // Zero-initialize
std::array output;
const UINT wFlags = 1 << 2; // If bit 2 is set, keyboard state is not changed (Windows 10, version 1607 and newer)
- auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, wFlags, layout);
+ auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), static_cast(output.size()) - 1, wFlags, layout);
if (output_bytes <= 0)
{
// If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW
diff --git a/src/common/Themes/icon_helpers.cpp b/src/common/Themes/icon_helpers.cpp
index e5387e85a9..c426a0c747 100644
--- a/src/common/Themes/icon_helpers.cpp
+++ b/src/common/Themes/icon_helpers.cpp
@@ -14,7 +14,7 @@ HRESULT GetIconIndexFromPath(_In_ PCWSTR path, _Out_ int* index)
if (!PathIsRelative(path))
{
DWORD attrib = GetFileAttributes(path);
- HIMAGELIST himl = (HIMAGELIST)SHGetFileInfo(path, attrib, &shFileInfo, sizeof(shFileInfo), (SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES));
+ auto himl =SHGetFileInfo(path, attrib, &shFileInfo, sizeof(shFileInfo), (SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES));
if (himl)
{
*index = shFileInfo.iIcon;
@@ -61,14 +61,14 @@ HBITMAP CreateBitmapFromIcon(_In_ HICON hIcon, _In_opt_ UINT width, _In_opt_ UIN
if (hBitmap != NULL)
{
// Select bitmap into DC
- HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);
+ HBITMAP hBitmapOld = static_cast(SelectObject(hDC, hBitmap));
if (hBitmapOld != NULL)
{
// Draw icon into DC
if (DrawIconEx(hDC, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL))
{
// Restore original bitmap in DC
- hBitmapResult = (HBITMAP)SelectObject(hDC, hBitmapOld);
+ hBitmapResult = static_cast(SelectObject(hDC, hBitmapOld));
hBitmapOld = NULL;
hBitmap = NULL;
}
diff --git a/src/common/Themes/theme_helpers.cpp b/src/common/Themes/theme_helpers.cpp
index 280eda9ded..c00bd92f76 100644
--- a/src/common/Themes/theme_helpers.cpp
+++ b/src/common/Themes/theme_helpers.cpp
@@ -28,10 +28,7 @@ AppTheme ThemeHelpers::GetAppTheme()
}
// convert bytes written to our buffer to an int, assuming little-endian
- auto i = int(buffer[3] << 24 |
- buffer[2] << 16 |
- buffer[1] << 8 |
- buffer[0]);
+ auto i = static_cast(buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]);
return AppTheme(i);
}
diff --git a/src/common/Themes/theme_listener.cpp b/src/common/Themes/theme_listener.cpp
index fb81a42e4c..3a31b0db3c 100644
--- a/src/common/Themes/theme_listener.cpp
+++ b/src/common/Themes/theme_listener.cpp
@@ -8,7 +8,7 @@
#pragma warning(disable : 4702)
DWORD WINAPI _checkTheme(LPVOID lpParam)
{
- auto listener = (ThemeListener*)lpParam;
+ auto listener = static_cast(lpParam);
listener->CheckTheme();
return 0;
}
diff --git a/src/common/Themes/windows_colors.cpp b/src/common/Themes/windows_colors.cpp
index a30329c181..e5a8eec732 100644
--- a/src/common/Themes/windows_colors.cpp
+++ b/src/common/Themes/windows_colors.cpp
@@ -11,7 +11,7 @@ DWORD WindowsColors::rgb_color(DWORD abgr_color)
}
DWORD WindowsColors::rgb_color(winrt::Windows::UI::Color color)
{
- return ((DWORD)color.R << 16) | ((DWORD)color.G << 8) | ((DWORD)color.B);
+ return static_cast((color.R << 16) | (color.G << 8) | (color.B));
}
WindowsColors::Color WindowsColors::get_button_face_color()
{
diff --git a/src/common/interop/PowerToys.Interop.vcxproj b/src/common/interop/PowerToys.Interop.vcxproj
index 9a88fcbb00..7f2f3f7da0 100644
--- a/src/common/interop/PowerToys.Interop.vcxproj
+++ b/src/common/interop/PowerToys.Interop.vcxproj
@@ -3,8 +3,6 @@
PowerToys.Interop
- Microsoft Corp.
- Copyright (C) 2022 Microsoft Corp.
diff --git a/src/common/interop/interop-tests/Microsoft.Interop.Tests.csproj b/src/common/interop/interop-tests/Microsoft.Interop.Tests.csproj
index 4efdbffc04..a89ba3f7ec 100644
--- a/src/common/interop/interop-tests/Microsoft.Interop.Tests.csproj
+++ b/src/common/interop/interop-tests/Microsoft.Interop.Tests.csproj
@@ -47,9 +47,9 @@
-
-
-
+
+
+
diff --git a/src/common/interop/interop.cpp b/src/common/interop/interop.cpp
index b64e577c07..c02ad5de98 100644
--- a/src/common/interop/interop.cpp
+++ b/src/common/interop/interop.cpp
@@ -187,6 +187,10 @@ public
return gcnew String(CommonSharedConstants::FZE_EXIT_EVENT);
}
+ static String ^ FZEToggleEvent() {
+ return gcnew String(CommonSharedConstants::FANCY_ZONES_EDITOR_TOGGLE_EVENT);
+ }
+
static String ^ ColorPickerSendSettingsTelemetryEvent() {
return gcnew String(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT);
}
@@ -211,6 +215,18 @@ public
return gcnew String(CommonSharedConstants::POWERACCENT_EXIT_EVENT);
}
+ static String ^ ShortcutGuideTriggerEvent() {
+ return gcnew String(CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT);
+ }
+
+ static String ^ RegistryPreviewTriggerEvent() {
+ return gcnew String(CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT);
+ }
+
+ static String ^ MeasureToolTriggerEvent() {
+ return gcnew String(CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT);
+ }
+
static String ^ GcodePreviewResizeEvent() {
return gcnew String(CommonSharedConstants::GCODE_PREVIEW_RESIZE_EVENT);
}
diff --git a/src/common/interop/keyboard_layout.cpp b/src/common/interop/keyboard_layout.cpp
index 441059bbb0..87562d4bf3 100644
--- a/src/common/interop/keyboard_layout.cpp
+++ b/src/common/interop/keyboard_layout.cpp
@@ -56,7 +56,7 @@ bool mapKeycodeToUnicode(const int vCode, HKL layout, const BYTE* keyState, std:
const UINT scanCode = MapVirtualKeyExW(vCode, MAPVK_VK_TO_VSC, layout);
// Get the unicode representation from the virtual key code and scan code pair
const UINT wFlags = 1 << 2; // If bit 2 is set, keyboard state is not changed (Windows 10, version 1607 and newer)
- const int result = ToUnicodeEx(vCode, scanCode, keyState, outBuffer.data(), (int)outBuffer.size(), wFlags, layout);
+ const int result = ToUnicodeEx(vCode, scanCode, keyState, outBuffer.data(), static_cast(outBuffer.size()), wFlags, layout);
return result != 0;
}
diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h
index 069bc10a79..69a69e7f28 100644
--- a/src/common/interop/shared_constants.h
+++ b/src/common/interop/shared_constants.h
@@ -28,6 +28,8 @@ namespace CommonSharedConstants
// Path to the event used to show Color Picker
const wchar_t SHOW_COLOR_PICKER_SHARED_EVENT[] = L"Local\\ShowColorPickerEvent-8c46be2a-3e05-4186-b56b-4ae986ef2525";
+ const wchar_t SHORTCUT_GUIDE_TRIGGER_EVENT[] = L"Local\\ShortcutGuide-TriggerEvent-d4275ad3-2531-4d19-9252-c0becbd9b496";
+
const wchar_t SHORTCUT_GUIDE_EXIT_EVENT[] = L"Local\\ShortcutGuide-ExitEvent-35697cdd-a3d2-47d6-a246-34efcc73eac0";
const wchar_t FANCY_ZONES_EDITOR_TOGGLE_EVENT[] = L"Local\\FancyZones-ToggleEditorEvent-1e174338-06a3-472b-874d-073b21c62f14";
@@ -44,6 +46,12 @@ namespace CommonSharedConstants
// Path to the event used by PowerOCR
const wchar_t SHOW_POWEROCR_SHARED_EVENT[] = L"Local\\PowerOCREvent-dc864e06-e1af-4ecc-9078-f98bee745e3a";
+ // Path to the event used by RegistryPreview
+ const wchar_t REGISTRY_PREVIEW_TRIGGER_EVENT[] = L"Local\\RegistryPreviewEvent-4C559468-F75A-4E7F-BC4F-9C9688316687";
+
+ // Path to the event used by MeasureTool
+ const wchar_t MEASURE_TOOL_TRIGGER_EVENT[] = L"Local\\MeasureToolEvent-3d46745f-09b3-4671-a577-236be7abd199";
+
// Path to the event used by GcodePreviewHandler
const wchar_t GCODE_PREVIEW_RESIZE_EVENT[] = L"Local\\PowerToysGcodePreviewResizeEvent-6ff1f9bd-ccbd-4b24-a79f-40a34fb0317d";
diff --git a/src/common/interop/two_way_pipe_message_ipc.cpp b/src/common/interop/two_way_pipe_message_ipc.cpp
index 69215665c7..7dd1dedf36 100644
--- a/src/common/interop/two_way_pipe_message_ipc.cpp
+++ b/src/common/interop/two_way_pipe_message_ipc.cpp
@@ -184,9 +184,9 @@ BOOL TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::GetLogonSID(HANDLE hToken,
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup;
- ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
+ ptg = static_cast(HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- dwLength);
+ dwLength));
if (ptg == NULL)
goto Cleanup;
@@ -213,14 +213,14 @@ BOOL TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::GetLogonSID(HANDLE hToken,
// Found the logon SID; make a copy of it.
dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
- *ppsid = (PSID)HeapAlloc(GetProcessHeap(),
+ *ppsid = static_cast(HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- dwLength);
+ dwLength));
if (*ppsid == NULL)
goto Cleanup;
if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))
{
- HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+ HeapFree(GetProcessHeap(), 0, static_cast(*ppsid));
goto Cleanup;
}
break;
@@ -233,7 +233,7 @@ Cleanup:
// Free the buffer for the token groups.
if (ptg != NULL)
- HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
+ HeapFree(GetProcessHeap(), 0, static_cast(ptg));
return bSuccess;
}
@@ -241,7 +241,7 @@ Cleanup:
VOID TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::FreeLogonSID(PSID* ppsid)
{
// From https://learn.microsoft.com/previous-versions/aa446670(v=vs.85)
- HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+ HeapFree(GetProcessHeap(), 0, static_cast(*ppsid));
}
int TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::change_pipe_security_allow_restricted_token(HANDLE handle, HANDLE token)
@@ -279,7 +279,7 @@ int TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::change_pipe_security_allow_r
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
- ea.Trustee.ptstrName = (LPTSTR)user_restricted;
+ ea.Trustee.ptstrName = static_cast(user_restricted);
if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl))
{
@@ -302,9 +302,9 @@ int TwoWayPipeMessageIPC::TwoWayPipeMessageIPCImpl::change_pipe_security_allow_r
error = 0;
Lclean_dacl:
- LocalFree((HLOCAL)new_dacl);
+ LocalFree(static_cast(new_dacl));
Lclean_sd:
- LocalFree((HLOCAL)sd);
+ LocalFree(static_cast(sd));
Lclean_sid:
FreeLogonSID(&user_restricted);
Ldone:
diff --git a/src/common/logger/logger_settings.h b/src/common/logger/logger_settings.h
index b424212314..fb64a11eae 100644
--- a/src/common/logger/logger_settings.h
+++ b/src/common/logger/logger_settings.h
@@ -47,6 +47,7 @@ struct LogSettings
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
+ inline const static std::string mouseJumpLoggerName = "mouse-jump";
inline const static std::string mousePointerCrosshairsLoggerName = "mouse-pointer-crosshairs";
inline const static std::string imageResizerLoggerName = "imageresizer";
inline const static std::string powerRenameLoggerName = "powerrename";
@@ -56,6 +57,8 @@ struct LogSettings
inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.txt";
inline const static std::string hostsLoggerName = "hosts";
inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.txt";
+ inline const static std::string registryPreviewLoggerName = "registrypreview";
+ inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.txt";
inline const static int retention = 30;
std::wstring logLevel;
LogSettings();
diff --git a/src/common/notifications/notifications.cpp b/src/common/notifications/notifications.cpp
index 7f03af0633..f6d5dbb11b 100644
--- a/src/common/notifications/notifications.cpp
+++ b/src/common/notifications/notifications.cpp
@@ -206,7 +206,7 @@ void notifications::show_toast(std::wstring message, std::wstring title, toast_p
show_toast_with_activations(std::move(message), std::move(title), {}, {}, std::move(params));
}
-inline void xml_escape(std::wstring data)
+constexpr inline void xml_escape(std::wstring data)
{
std::wstring buffer;
buffer.reserve(data.size());
diff --git a/src/common/updating/updating.cpp b/src/common/updating/updating.cpp
index 3bb560319a..c0e194403b 100644
--- a/src/common/updating/updating.cpp
+++ b/src/common/updating/updating.cpp
@@ -8,6 +8,9 @@
#include
#include
+#include
+
+using namespace registry::install_scope;
namespace // Strings in this namespace should not be localized
{
@@ -42,9 +45,16 @@ namespace updating
std::pair extract_installer_asset_download_info(const json::JsonObject& release_object)
{
const std::wstring_view required_architecture = get_architecture_string(get_current_architecture());
- constexpr const std::wstring_view required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN;
+ std::wstring_view required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN;
// Desc-sorted by its priority
const std::array asset_extensions = { L".exe", L".msi" };
+
+ const InstallScope current_install_scope = get_current_install_scope();
+ if (current_install_scope == InstallScope::PerUser)
+ {
+ required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN_USER;
+ }
+
for (const auto asset_extension : asset_extensions)
{
for (auto asset_elem : release_object.GetNamedArray(L"assets"))
diff --git a/src/common/updating/updating.h b/src/common/updating/updating.h
index a5a15e47de..11ab3b95fd 100644
--- a/src/common/updating/updating.h
+++ b/src/common/updating/updating.h
@@ -31,4 +31,5 @@ namespace updating
// non-localized
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup";
+ constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN_USER = L"powertoysusersetup";
}
diff --git a/src/common/updating/updating.vcxproj b/src/common/updating/updating.vcxproj
index b68206c358..04625c09cf 100644
--- a/src/common/updating/updating.vcxproj
+++ b/src/common/updating/updating.vcxproj
@@ -15,6 +15,7 @@
v143
+
diff --git a/src/common/utils/HDropIterator.h b/src/common/utils/HDropIterator.h
index 3b52d65bab..11ffab5863 100644
--- a/src/common/utils/HDropIterator.h
+++ b/src/common/utils/HDropIterator.h
@@ -19,7 +19,7 @@ public:
if (SUCCEEDED(pDataObject->GetData(&formatetc, &m_medium)))
{
- _listCount = DragQueryFile((HDROP)m_medium.hGlobal, 0xFFFFFFFF, NULL, 0);
+ _listCount = DragQueryFile(static_cast(m_medium.hGlobal), 0xFFFFFFFF, NULL, 0);
}
else
{
@@ -52,10 +52,10 @@ public:
LPTSTR CurrentItem() const
{
- UINT cch = DragQueryFile((HDROP)m_medium.hGlobal, _current, NULL, 0) + 1;
- LPTSTR pszPath = (LPTSTR)malloc(sizeof(TCHAR) * cch);
+ UINT cch = DragQueryFile(static_cast(m_medium.hGlobal), _current, NULL, 0) + 1;
+ LPTSTR pszPath = static_cast(malloc(sizeof(TCHAR) * cch));
- DragQueryFile((HDROP)m_medium.hGlobal, _current, pszPath, cch);
+ DragQueryFile(static_cast(m_medium.hGlobal), _current, pszPath, cch);
return pszPath;
}
diff --git a/src/common/utils/HttpClient.h b/src/common/utils/HttpClient.h
index 86b201a5d1..8726368fbb 100644
--- a/src/common/utils/HttpClient.h
+++ b/src/common/utils/HttpClient.h
@@ -57,7 +57,7 @@ namespace http
totalBytesRead += buffer.Length();
if (progressUpdateCallback)
{
- float percentage = (float)totalBytesRead / totalBytes;
+ float percentage = static_cast(totalBytesRead) / totalBytes;
progressUpdateCallback(percentage);
}
diff --git a/src/common/utils/MsiUtils.h b/src/common/utils/MsiUtils.h
index 1489685005..f369dd3b6f 100644
--- a/src/common/utils/MsiUtils.h
+++ b/src/common/utils/MsiUtils.h
@@ -12,14 +12,16 @@
namespace // Strings in this namespace should not be localized
{
const inline wchar_t POWER_TOYS_UPGRADE_CODE[] = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
+ const inline wchar_t POWER_TOYS_UPGRADE_CODE_USER[] = L"{D8B559DB-4C98-487A-A33F-50A8EEE42726}";
const inline wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
}
-std::optional GetMsiPackageInstalledPath()
+std::optional GetMsiPackageInstalledPath(bool perUser)
{
constexpr size_t guid_length = 39;
wchar_t product_ID[guid_length];
- if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, product_ID); !found)
+ std::wstring upgradeCode = (perUser ? POWER_TOYS_UPGRADE_CODE_USER : POWER_TOYS_UPGRADE_CODE);
+ if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(upgradeCode.c_str(), 0, 0, product_ID); !found)
{
return std::nullopt;
}
diff --git a/src/common/utils/UnhandledExceptionHandler.h b/src/common/utils/UnhandledExceptionHandler.h
index a3a69b2932..bbe2e81f24 100644
--- a/src/common/utils/UnhandledExceptionHandler.h
+++ b/src/common/utils/UnhandledExceptionHandler.h
@@ -93,7 +93,7 @@ inline std::wstring GetModuleName(HANDLE process, const STACKFRAME64& stack)
return std::wstring();
}
- if (!GetModuleFileNameW((HINSTANCE)moduleBase, modulePath, MAX_PATH))
+ if (!GetModuleFileNameW(reinterpret_cast(moduleBase), modulePath, MAX_PATH))
{
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
@@ -105,7 +105,7 @@ inline std::wstring GetModuleName(HANDLE process, const STACKFRAME64& stack)
inline std::wstring GetName(HANDLE process, const STACKFRAME64& stack)
{
- static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
+ static IMAGEHLP_SYMBOL64* pSymbol = static_cast(malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR)));
if (!pSymbol)
{
return std::wstring();
diff --git a/src/common/utils/elevation.h b/src/common/utils/elevation.h
index 2615d4b8ad..269f395d44 100644
--- a/src/common/utils/elevation.h
+++ b/src/common/utils/elevation.h
@@ -198,7 +198,7 @@ inline bool drop_elevated_privileges()
TOKEN_MANDATORY_LABEL label = { 0 };
label.Label.Attributes = SE_GROUP_INTEGRITY;
label.Label.Sid = medium_sid;
- DWORD size = (DWORD)sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid);
+ DWORD size = static_cast(sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid));
BOOL result = SetTokenInformation(token, TokenIntegrityLevel, &label, size);
LocalFree(medium_sid);
@@ -294,8 +294,9 @@ inline bool run_non_elevated(const std::wstring& file, const std::wstring& param
siex.StartupInfo.cb = sizeof(siex);
PROCESS_INFORMATION pi = { 0 };
+
auto succeeded = CreateProcessW(file.c_str(),
- const_cast(executable_args.c_str()),
+ &executable_args[0],
nullptr,
nullptr,
FALSE,
@@ -395,8 +396,9 @@ inline bool run_same_elevation(const std::wstring& file, const std::wstring& par
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = { 0 };
+
auto succeeded = CreateProcessW(file.c_str(),
- const_cast(executable_args.c_str()),
+ &executable_args[0],
nullptr,
nullptr,
FALSE,
@@ -464,7 +466,7 @@ inline bool check_user_is_admin()
}
// Allocate the buffer.
- pGroupInfo = (PTOKEN_GROUPS)GlobalAlloc(GPTR, dwSize);
+ pGroupInfo = static_cast(GlobalAlloc(GPTR, dwSize));
// Call GetTokenInformation again to get the group information.
if (!GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize))
diff --git a/src/common/utils/exec.h b/src/common/utils/exec.h
index feeda08b89..ec76c92876 100644
--- a/src/common/utils/exec.h
+++ b/src/common/utils/exec.h
@@ -4,8 +4,11 @@
#include
// disable warning 26471 - Don't use reinterpret_cast. A cast from void* can use static_cast
+// disable warning 26492 - Don't use const_cast to cast away const
+// disable warning 26493 - Don't use C-style casts
+// Disable 26497 for winrt - This function function-name could be marked constexpr if compile-time evaluation is desired.
#pragma warning(push)
-#pragma warning(disable: 26471)
+#pragma warning(disable : 26471 26492 26493 26497)
#include
#pragma warning(pop)
diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h
index c77c036c51..e105749812 100644
--- a/src/common/utils/gpo.h
+++ b/src/common/utils/gpo.h
@@ -38,6 +38,7 @@ namespace powertoys_gpo {
const std::wstring POLICY_CONFIGURE_ENABLED_KEYBOARD_MANAGER = L"ConfigureEnabledUtilityKeyboardManager";
const std::wstring POLICY_CONFIGURE_ENABLED_FIND_MY_MOUSE = L"ConfigureEnabledUtilityFindMyMouse";
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_HIGHLIGHTER = L"ConfigureEnabledUtilityMouseHighlighter";
+ const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_JUMP = L"ConfigureEnabledUtilityMouseJump";
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS = L"ConfigureEnabledUtilityMousePointerCrosshairs";
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_RENAME = L"ConfigureEnabledUtilityPowerRename";
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER = L"ConfigureEnabledUtilityPowerLauncher";
@@ -45,12 +46,23 @@ namespace powertoys_gpo {
const std::wstring POLICY_CONFIGURE_ENABLED_SCREEN_RULER = L"ConfigureEnabledUtilityScreenRuler";
const std::wstring POLICY_CONFIGURE_ENABLED_SHORTCUT_GUIDE = L"ConfigureEnabledUtilityShortcutGuide";
const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor";
+ const std::wstring POLICY_CONFIGURE_ENABLED_PASTE_PLAIN = L"ConfigureEnabledUtilityPastePlain";
const std::wstring POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE = L"ConfigureEnabledUtilityVideoConferenceMute";
+ const std::wstring POLICY_CONFIGURE_ENABLED_REGISTRY_PREVIEW = L"ConfigureEnabledUtilityRegistryPreview";
+
+ // The registry value names for PowerToys installer and update policies.
+ const std::wstring POLICY_DISABLE_PER_USER_INSTALLATION = L"PerUserInstallationDisabled";
+ const std::wstring POLICY_DISABLE_AUTOMATIC_UPDATE_DOWNLOAD = L"AutomaticUpdateDownloadDisabled";
+ const std::wstring POLICY_SUSPEND_NEW_UPDATE_TOAST = L"SuspendNewUpdateAvailableToast";
+ const std::wstring POLICY_DISABLE_PERIODIC_UPDATE_CHECK = L"PeriodicUpdateCheckDisabled";
+
+ // The registry value names for other PowerToys policies.
+ const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
inline gpo_rule_configured_t getConfiguredValue(const std::wstring& registry_value_name)
{
HKEY key{};
- DWORD value = (DWORD) -2;
+ DWORD value = 0xFFFFFFFE;
DWORD valueSize = sizeof(value);
bool machine_key_found = true;
@@ -62,7 +74,7 @@ namespace powertoys_gpo {
if(machine_key_found)
{
// If the path was found in the machine, we need to check if the value for the policy exists.
- auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, (LPBYTE)&value, &valueSize);
+ auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, reinterpret_cast(&value), &valueSize);
RegCloseKey(key);
@@ -82,7 +94,7 @@ namespace powertoys_gpo {
}
return gpo_rule_configured_unavailable;
}
- auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, (LPBYTE)&value, &valueSize);
+ auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, reinterpret_cast(&value), &valueSize);
RegCloseKey(key);
if (res != ERROR_SUCCESS) {
@@ -195,6 +207,11 @@ namespace powertoys_gpo {
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_HIGHLIGHTER);
}
+ inline gpo_rule_configured_t getConfiguredMouseJumpEnabledValue()
+ {
+ return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_JUMP);
+ }
+
inline gpo_rule_configured_t getConfiguredMousePointerCrosshairsEnabledValue()
{
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS);
@@ -230,9 +247,44 @@ namespace powertoys_gpo {
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR);
}
+ inline gpo_rule_configured_t getConfiguredPastePlainEnabledValue()
+ {
+ return getConfiguredValue(POLICY_CONFIGURE_ENABLED_PASTE_PLAIN);
+ }
+
inline gpo_rule_configured_t getConfiguredVideoConferenceMuteEnabledValue()
{
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE);
}
+ inline gpo_rule_configured_t getConfiguredRegistryPreviewEnabledValue()
+ {
+ return getConfiguredValue(POLICY_CONFIGURE_ENABLED_REGISTRY_PREVIEW);
+ }
+
+ inline gpo_rule_configured_t getDisablePerUserInstallationValue()
+ {
+ return getConfiguredValue(POLICY_DISABLE_PER_USER_INSTALLATION);
+ }
+
+ inline gpo_rule_configured_t getDisableAutomaticUpdateDownloadValue()
+ {
+ return getConfiguredValue(POLICY_DISABLE_AUTOMATIC_UPDATE_DOWNLOAD);
+ }
+
+ inline gpo_rule_configured_t getSuspendNewUpdateToastValue()
+ {
+ return getConfiguredValue(POLICY_SUSPEND_NEW_UPDATE_TOAST);
+ }
+
+ inline gpo_rule_configured_t getDisablePeriodicUpdateCheckValue()
+ {
+ return getConfiguredValue(POLICY_DISABLE_PERIODIC_UPDATE_CHECK);
+ }
+
+ inline gpo_rule_configured_t getAllowExperimentationValue()
+ {
+ return getConfiguredValue(POLICY_ALLOW_EXPERIMENTATION);
+ }
+
}
diff --git a/src/common/utils/modulesRegistry.h b/src/common/utils/modulesRegistry.h
index 62d0d35cf2..1f58ab55ca 100644
--- a/src/common/utils/modulesRegistry.h
+++ b/src/common/utils/modulesRegistry.h
@@ -192,6 +192,24 @@ inline registry::ChangeSet getStlThumbnailHandlerChangeSet(const std::wstring in
NonLocalizable::ExtSTL);
}
+inline registry::ChangeSet getRegistryPreviewChangeSet(const std::wstring installationDir,const bool perUser)
+{
+ const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+
+ using vec_t = std::vector;
+ vec_t changes;
+
+ std::wstring command = installationDir;
+ command.append(L"\\modules\\RegistryPreview\\PowerToys.RegistryPreview.exe \"%1\"");
+ changes.push_back({ scope, L"Software\\Classes\\regfile\\shell\\preview\\command", std::nullopt, command });
+
+ std::wstring icon_path = installationDir;
+ icon_path.append(L"\\modules\\RegistryPreview\\app.ico");
+ changes.push_back({ scope, L"Software\\Classes\\regfile\\shell\\preview", L"icon", icon_path });
+
+ return { changes };
+}
+
inline std::vector getAllOnByDefaultModulesChangeSets(const std::wstring installationDir)
{
constexpr bool PER_USER = true;
@@ -201,7 +219,8 @@ inline std::vector getAllOnByDefaultModulesChangeSets(const
getGcodePreviewHandlerChangeSet(installationDir, PER_USER),
getSvgThumbnailHandlerChangeSet(installationDir, PER_USER),
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
- getStlThumbnailHandlerChangeSet(installationDir, PER_USER) };
+ getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
+ getRegistryPreviewChangeSet(installationDir, PER_USER) };
}
inline std::vector getAllModulesChangeSets(const std::wstring installationDir)
@@ -215,5 +234,6 @@ inline std::vector getAllModulesChangeSets(const std::wstri
getSvgThumbnailHandlerChangeSet(installationDir, PER_USER),
getPdfThumbnailHandlerChangeSet(installationDir, PER_USER),
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
- getStlThumbnailHandlerChangeSet(installationDir, PER_USER) };
+ getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
+ getRegistryPreviewChangeSet(installationDir, PER_USER) };
}
diff --git a/src/common/utils/process_path.h b/src/common/utils/process_path.h
index 382a1d2ea5..56129a9bb7 100644
--- a/src/common/utils/process_path.h
+++ b/src/common/utils/process_path.h
@@ -15,7 +15,7 @@ inline std::wstring get_process_path(DWORD pid) noexcept
{
name.resize(MAX_PATH);
DWORD name_length = static_cast(name.length());
- if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0)
+ if (QueryFullProcessImageNameW(process, 0, name.data(), &name_length) == 0)
{
name_length = 0;
}
@@ -118,5 +118,5 @@ inline std::wstring get_module_folderpath(HMODULE mod = nullptr, const bool remo
{
PathRemoveFileSpecW(buffer);
}
- return { buffer, (UINT)lstrlenW(buffer) };
+ return { buffer, static_cast(lstrlenW(buffer))};
}
diff --git a/src/common/utils/registry.h b/src/common/utils/registry.h
index d254457999..57507e36b1 100644
--- a/src/common/utils/registry.h
+++ b/src/common/utils/registry.h
@@ -16,6 +16,86 @@
namespace registry
{
+ namespace install_scope
+ {
+ const wchar_t INSTALL_SCOPE_REG_KEY[] = L"Software\\Classes\\powertoys\\";
+
+ enum class InstallScope
+ {
+ PerMachine = 0,
+ PerUser,
+ };
+
+ inline const InstallScope get_current_install_scope()
+ {
+ // Open HKLM key
+ HKEY perMachineKey{};
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ INSTALL_SCOPE_REG_KEY,
+ 0,
+ KEY_READ,
+ &perMachineKey) != ERROR_SUCCESS)
+ {
+ // Open HKCU key
+ HKEY perUserKey{};
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ INSTALL_SCOPE_REG_KEY,
+ 0,
+ KEY_READ,
+ &perUserKey) != ERROR_SUCCESS)
+ {
+ // both keys are missing
+ return InstallScope::PerMachine;
+ }
+ else
+ {
+ DWORD dataSize{};
+ if (RegGetValueW(
+ perUserKey,
+ nullptr,
+ L"InstallScope",
+ RRF_RT_REG_SZ,
+ nullptr,
+ nullptr,
+ &dataSize) != ERROR_SUCCESS)
+ {
+ // HKCU key is missing
+ RegCloseKey(perUserKey);
+ return InstallScope::PerMachine;
+ }
+
+ std::wstring data;
+ data.resize(dataSize / sizeof(wchar_t));
+
+ if (RegGetValueW(
+ perUserKey,
+ nullptr,
+ L"InstallScope",
+ RRF_RT_REG_SZ,
+ nullptr,
+ &data[0],
+ &dataSize) != ERROR_SUCCESS)
+ {
+ // HKCU key is missing
+ RegCloseKey(perUserKey);
+ return InstallScope::PerMachine;
+ }
+ RegCloseKey(perUserKey);
+
+ if (data.contains(L"perUser"))
+ {
+ return InstallScope::PerUser;
+ }
+ }
+ }
+
+ return InstallScope::PerMachine;
+ }
+ }
+
+ template
+ inline constexpr bool always_false_v = false;
+
namespace detail
{
struct on_exit
@@ -27,9 +107,6 @@ namespace registry
~on_exit() { f(); }
};
- template
- inline constexpr bool always_false_v = false;
-
template
struct overloaded : Ts...
{
@@ -241,7 +318,7 @@ namespace registry
switch (type)
{
case REG_DWORD:
- return *(DWORD*)buffer;
+ return *reinterpret_cast(buffer);
case REG_SZ:
{
if (!valueSize)
diff --git a/src/common/utils/timeutil.h b/src/common/utils/timeutil.h
index 8242cef9d0..b82e7981bd 100644
--- a/src/common/utils/timeutil.h
+++ b/src/common/utils/timeutil.h
@@ -60,7 +60,7 @@ namespace timeutil
inline int64_t in_days(const std::time_t to, const std::time_t from)
{
- return static_cast(std::difftime(to, from) / (3600 * (int64_t)24));
+ return static_cast(std::difftime(to, from) / (3600 * 24LL));
}
}
}
diff --git a/src/common/utils/winapi_error.h b/src/common/utils/winapi_error.h
index b4cc01aa83..dec9f93146 100644
--- a/src/common/utils/winapi_error.h
+++ b/src/common/utils/winapi_error.h
@@ -35,7 +35,7 @@ inline void show_last_error_message(const wchar_t* functionName, DWORD dw, const
{
return;
}
- LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(functionName) + 40) * sizeof(WCHAR));
+ LPWSTR lpDisplayBuf = static_cast(LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(functionName) + 40) * sizeof(WCHAR)));
if (lpDisplayBuf != NULL)
{
StringCchPrintfW(lpDisplayBuf,
@@ -44,7 +44,7 @@ inline void show_last_error_message(const wchar_t* functionName, DWORD dw, const
functionName,
system_message->c_str(),
dw);
- MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, errorTitle, MB_OK | MB_ICONERROR);
+ MessageBoxW(NULL, lpDisplayBuf, errorTitle, MB_OK | MB_ICONERROR);
LocalFree(lpDisplayBuf);
}
}
diff --git a/src/common/utils/window.h b/src/common/utils/window.h
index 36e4b671c3..cfcf20534a 100644
--- a/src/common/utils/window.h
+++ b/src/common/utils/window.h
@@ -60,7 +60,7 @@ template
inline T GetWindowCreateParam(LPARAM lparam)
{
static_assert(sizeof(T) <= sizeof(void*));
- T data{ (T)(reinterpret_cast(lparam)->lpCreateParams) };
+ T data{ static_cast (reinterpret_cast(lparam)->lpCreateParams) };
return data;
}
@@ -74,5 +74,5 @@ inline void StoreWindowParam(HWND window, T data)
template
inline T GetWindowParam(HWND window)
{
- return (T)GetWindowLongPtrW(window, GWLP_USERDATA);
+ return reinterpret_cast (GetWindowLongPtrW(window, GWLP_USERDATA));
}
diff --git a/src/common/version/version.h b/src/common/version/version.h
index 5e78481c42..8c3ffd302d 100644
--- a/src/common/version/version.h
+++ b/src/common/version/version.h
@@ -13,7 +13,7 @@
#define PRODUCT_VERSION_STRING FILE_VERSION_STRING
#define COMPANY_NAME "Microsoft Corporation"
-#define COPYRIGHT_NOTE "Copyright (C) 2022 Microsoft Corporation"
+#define COPYRIGHT_NOTE "Copyright (C) 2023 Microsoft Corporation"
#define PRODUCT_NAME "PowerToys"
#include
diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx
index 037bf1cc2d..65f8b55a26 100644
--- a/src/gpo/assets/PowerToys.admx
+++ b/src/gpo/assets/PowerToys.admx
@@ -1,18 +1,22 @@
-
+
-
+
+
+
-
+
+
+
@@ -216,6 +220,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -246,7 +270,17 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -285,6 +319,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml
index 9a07cd42f9..a551c8b4ba 100644
--- a/src/gpo/assets/en-US/PowerToys.adml
+++ b/src/gpo/assets/en-US/PowerToys.adml
@@ -1,14 +1,17 @@
-
+
PowerToys
PowerToys
Microsoft PowerToys
+ Installer and Updates
PowerToys version 0.64.0 or later
+ PowerToys version 0.68.0 or later
+ PowerToys version 0.69.0 or later
This policy configures the enabled state for a PowerToys utility.
@@ -27,6 +30,38 @@ If you enable this setting, the utility will be always enabled and the user won'
If you disable this setting, the utility will be always disabled and the user won't be able to enable it.
If you don't configure this setting, users are able to disable or enable the utility.
+
+ This policy configures whether per-user PowerToys installation is allowed or not.
+
+If enabled, per-user installation is not allowed.
+
+If disabled or not configured, per-user installation is allowed.
+
+ This policy configures whether automatic downloads of available updates are disabled or not. (On metered connections updates are never downloaded.)
+
+If enabled, automatic downloads are disabled.
+
+If disabled or not configured, the user is in control of automatic downloads setting.
+
+ This policy configures whether the action center notification for new updates is suspended for 2 minor releases. (Example: if the installed version is v0.60.0, then the next notification is shown for the v0.63.* release.)
+
+If enabled, the notification is suspended.
+
+If disabled or not configured, the notification is shown.
+
+Note: The notification about new major versions is always displayed.
+
+ This policy allows you to disable automatic update checks running in the background. (The manual check in PT Settings is not affected by this policy.)
+
+If enabled, the automatic update checks are disabled.
+
+If disabled or not configured, the automatic update checks are enabled.
+
+ This policy configures whether PowerToys experimentation is allowed. With experimentation allowed the user sees the new features being experimented if it gets selected as part of the test group. (Experimentation will only happen on Windows Insider builds.)
+
+If this setting is not configured or enabled, the user can control experimentation in the PowerToys settings menu.
+
+If this setting is disabled, experimentation is not allowed.
Always On Top: Configure enabled state
Awake: Configure enabled state
@@ -47,14 +82,22 @@ If you don't configure this setting, users are able to disable or enable the uti
Keyboard Manager: Configure enabled state
Find My Mouse: Configure enabled state
Mouse Highlighter: Configure enabled state
+ Mouse Jump: Configure enabled state
Mouse Pointer Crosshairs: Configure enabled state
+ Paste as Plain Text: Configure enabled state
Power Rename: Configure enabled state
PowerToys Run: Configure enabled state
Quick Accent: Configure enabled state
+ Registry Preview: Configure enabled state
Screen Ruler: Configure enabled state
Shortcut Guide: Configure enabled state
Video Conference Mute: Configure enabled state
+ Disable per-user installation
+ Disable automatic downloads
+ Suspend Action Center notification for new updates
+ Disable automatic update checks
+ Allow Experimentation
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
index 6db892d2fb..5015d2d9e3 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
+++ b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
@@ -7,6 +7,9 @@
#include "Trace.h"
#include "Generated Files/resource.h"
+#include
+#include
+
// Implementations of inherited IUnknown methods
IFACEMETHODIMP ExplorerCommand::QueryInterface(REFIID riid, void** ppv)
@@ -46,9 +49,10 @@ IFACEMETHODIMP ExplorerCommand::GetTitle(IShellItemArray* psiItemArray, LPWSTR*
IFACEMETHODIMP ExplorerCommand::GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon)
{
- // Path to the icon should be computed relative to the path of this module
- ppszIcon = NULL;
- return E_NOTIMPL;
+ std::wstring iconResourcePath = get_module_filename();
+ iconResourcePath += L",-";
+ iconResourcePath += std::to_wstring(IDI_FILELOCKSMITH);
+ return SHStrDup(iconResourcePath.c_str(), ppszIcon);
}
IFACEMETHODIMP ExplorerCommand::GetToolTip(IShellItemArray* psiItemArray, LPWSTR* ppszInfotip)
@@ -129,7 +133,18 @@ IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UI
mii.fState = MFS_ENABLED;
- // TODO icon from file
+ // icon from file
+ HICON hIcon = static_cast(LoadImage(globals::instance, MAKEINTRESOURCE(IDI_FILELOCKSMITH), IMAGE_ICON, 16, 16, 0));
+ if (hIcon)
+ {
+ mii.fMask |= MIIM_BITMAP;
+ if (m_hbmpIcon == NULL)
+ {
+ m_hbmpIcon = CreateBitmapFromIcon(hIcon);
+ }
+ mii.hbmpItem = m_hbmpIcon;
+ DestroyIcon(hIcon);
+ }
if (!InsertMenuItem(hmenu, indexMenu, TRUE, &mii))
{
@@ -226,30 +241,6 @@ ExplorerCommand::~ExplorerCommand()
--globals::ref_count;
}
-// Implementation taken from src/common/utils
-// TODO reference that function
-inline std::wstring get_module_folderpath(HMODULE mod = nullptr, const bool removeFilename = true)
-{
- wchar_t buffer[MAX_PATH + 1];
- DWORD actual_length = GetModuleFileNameW(mod, buffer, MAX_PATH + 1);
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- const DWORD long_path_length = 0xFFFF; // should be always enough
- std::wstring long_filename(long_path_length, L'\0');
- actual_length = GetModuleFileNameW(mod, long_filename.data(), long_path_length);
- PathRemoveFileSpecW(long_filename.data());
- long_filename.resize(std::wcslen(long_filename.data()));
- long_filename.shrink_to_fit();
- return long_filename;
- }
-
- if (removeFilename)
- {
- PathRemoveFileSpecW(buffer);
- }
- return { buffer, (UINT)lstrlenW(buffer) };
-}
-
HRESULT ExplorerCommand::LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer)
{
// Compute exe path
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
index 5d6e2aad40..9da12236be 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
+++ b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
@@ -42,6 +42,8 @@ public:
~ExplorerCommand();
private:
+ HBITMAP m_hbmpIcon = nullptr;
+
// Helpers
HRESULT LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer);
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.base.rc b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.base.rc
index b55a2b37ad..ea565d98f9 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.base.rc
+++ b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.base.rc
@@ -48,3 +48,10 @@ BEGIN
VALUE "Translation", 0x409, 1200
END
END
+
+// Non-localizable
+//////////////////////////////
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_FILELOCKSMITH ICON "..\\FileLocksmithUI\\Assets\\Icon.ico"
\ No newline at end of file
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
index 4e69eba166..d21a9eb775 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
+++ b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
@@ -280,6 +280,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {98537082-0fdb-40de-abd8-0dc5a4269bab}
+
{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/resource.base.h b/src/modules/FileLocksmith/FileLocksmithExt/resource.base.h
index 1ffbbe0caa..955a04e15b 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/resource.base.h
+++ b/src/modules/FileLocksmith/FileLocksmithExt/resource.base.h
@@ -8,6 +8,7 @@
#define FILE_DESCRIPTION "PowerToys File Locksmith Static Library"
#define INTERNAL_NAME "PowerToys.FileLocksmithLib.lib"
#define ORIGINAL_FILENAME "PowerToys.FileLocksmithLib.lib"
+#define IDI_FILELOCKSMITH 1001
// Non-localizable
//////////////////////////////
diff --git a/src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp b/src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp
index 3968348997..cc0fce4a79 100644
--- a/src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp
+++ b/src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp
@@ -151,7 +151,7 @@ namespace FileLocksmith::Interop
if (!stream)
{
- return false;
+ return false;
}
stream.close();
@@ -178,7 +178,7 @@ namespace FileLocksmith::Interop
return false;
}
- /* Adapted from "https://learn.microsoft.com/en-us/windows/win32/secauthz/enabling-and-disabling-privileges-in-c--" */
+ /* Adapted from "https://learn.microsoft.com/windows/win32/secauthz/enabling-and-disabling-privileges-in-c--" */
static System::Boolean SetDebugPrivilege()
{
HANDLE hToken;
diff --git a/src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs b/src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs
index a55714470a..15312c5969 100644
--- a/src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs
+++ b/src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs
@@ -4,7 +4,6 @@
using System;
using System.Linq;
-using FileLocksmithUI.Helpers;
using ManagedCommon;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
@@ -23,6 +22,8 @@ namespace FileLocksmithUI
///
public App()
{
+ Logger.InitializeLogger("\\File Locksmith\\FileLocksmithUI\\Logs");
+
this.InitializeComponent();
}
diff --git a/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj b/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj
index 094cd7f13c..c2dfe3edfe 100644
--- a/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj
+++ b/src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj
@@ -62,15 +62,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/FileLocksmith/FileLocksmithUI/Helpers/Logger.cs b/src/modules/FileLocksmith/FileLocksmithUI/Helpers/Logger.cs
deleted file mode 100644
index 2ec357c3cf..0000000000
--- a/src/modules/FileLocksmith/FileLocksmithUI/Helpers/Logger.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-
-namespace FileLocksmithUI.Helpers
-{
- public static class Logger
- {
- private static readonly string ApplicationLogPath = Path.Combine(interop.Constants.AppDataPath(), "File Locksmith\\FileLocksmithUI\\Logs");
-
- static Logger()
- {
- if (!Directory.Exists(ApplicationLogPath))
- {
- Directory.CreateDirectory(ApplicationLogPath);
- }
-
- // Using InvariantCulture since this is used for a log file name
- var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
-
- Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
-
- Trace.AutoFlush = true;
- }
-
- public static void LogError(string message)
- {
- Log(message, "ERROR");
- }
-
- public static void LogError(string message, Exception ex)
- {
- Log(
- message + Environment.NewLine +
- ex?.Message + Environment.NewLine +
- "Inner exception: " + Environment.NewLine +
- ex?.InnerException?.Message + Environment.NewLine +
- "Stack trace: " + Environment.NewLine +
- ex?.StackTrace,
- "ERROR");
- }
-
- public static void LogWarning(string message)
- {
- Log(message, "WARNING");
- }
-
- public static void LogInfo(string message)
- {
- Log(message, "INFO");
- }
-
- private static void Log(string message, string type)
- {
- Trace.WriteLine(type + ": " + DateTime.Now.TimeOfDay);
- Trace.Indent();
- Trace.WriteLine(GetCallerInfo());
- Trace.WriteLine(message);
- Trace.Unindent();
- }
-
- private static string GetCallerInfo()
- {
- StackTrace stackTrace = new StackTrace();
-
- var methodName = stackTrace.GetFrame(3)?.GetMethod();
- var className = methodName?.DeclaringType.Name;
- return "[Method]: " + methodName?.Name + " [Class]: " + className;
- }
- }
-}
diff --git a/src/modules/FileLocksmith/FileLocksmithUI/ViewModels/MainViewModel.cs b/src/modules/FileLocksmith/FileLocksmithUI/ViewModels/MainViewModel.cs
index 6e0adf2dcf..d473a05c58 100644
--- a/src/modules/FileLocksmith/FileLocksmithUI/ViewModels/MainViewModel.cs
+++ b/src/modules/FileLocksmith/FileLocksmithUI/ViewModels/MainViewModel.cs
@@ -12,7 +12,7 @@ using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FileLocksmith.Interop;
-using global::FileLocksmithUI.Helpers;
+using ManagedCommon;
namespace PowerToys.FileLocksmithUI.ViewModels
{
diff --git a/src/modules/FileLocksmith/FileLocksmithUI/app.manifest b/src/modules/FileLocksmith/FileLocksmithUI/app.manifest
new file mode 100644
index 0000000000..575aa4df9d
--- /dev/null
+++ b/src/modules/FileLocksmith/FileLocksmithUI/app.manifest
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/Hosts/Hosts.Tests/EntryTest.cs b/src/modules/Hosts/Hosts.Tests/EntryTest.cs
index 7a61fe147c..c316ecda53 100644
--- a/src/modules/Hosts/Hosts.Tests/EntryTest.cs
+++ b/src/modules/Hosts/Hosts.Tests/EntryTest.cs
@@ -28,7 +28,7 @@ namespace Hosts.Tests
[DataRow("# # \t10.1.1.1 host#comment", "10.1.1.1", "host", "comment", false)]
public void Valid_Entry_SingleHost(string line, string address, string host, string comment, bool active)
{
- var entry = new Entry(line);
+ var entry = new Entry(0, line);
Assert.AreEqual(entry.Address, address);
Assert.AreEqual(entry.Hosts, host);
@@ -52,7 +52,7 @@ namespace Hosts.Tests
[DataRow("#10.1.1.1 host host.local#comment", "10.1.1.1", "host host.local", "comment", false)]
public void Valid_Entry_MultipleHosts(string line, string address, string host, string comment, bool active)
{
- var entry = new Entry(line);
+ var entry = new Entry(0, line);
Assert.AreEqual(entry.Address, address);
Assert.AreEqual(entry.Hosts, host);
@@ -76,7 +76,7 @@ namespace Hosts.Tests
[DataRow("host 10.1.1.1")]
public void Not_Valid_Entry(string line)
{
- var entry = new Entry(line);
+ var entry = new Entry(0, line);
Assert.IsFalse(entry.Valid);
}
}
diff --git a/src/modules/Hosts/Hosts.Tests/Hosts.Tests.csproj b/src/modules/Hosts/Hosts.Tests/Hosts.Tests.csproj
index 40c7baf060..dc75cf4b59 100644
--- a/src/modules/Hosts/Hosts.Tests/Hosts.Tests.csproj
+++ b/src/modules/Hosts/Hosts.Tests/Hosts.Tests.csproj
@@ -14,13 +14,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/modules/Hosts/Hosts.Tests/HostsServiceTest.cs b/src/modules/Hosts/Hosts.Tests/HostsServiceTest.cs
index 1de3d52bc2..7756c434d3 100644
--- a/src/modules/Hosts/Hosts.Tests/HostsServiceTest.cs
+++ b/src/modules/Hosts/Hosts.Tests/HostsServiceTest.cs
@@ -70,7 +70,7 @@ namespace Hosts.Tests
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
var (_, entries) = await service.ReadAsync();
- entries.Add(new Entry("10.1.1.30", "host30 host30.local", "new entry", false));
+ entries.Add(new Entry(0, "10.1.1.30", "host30 host30.local", "new entry", false));
await service.WriteAsync(string.Empty, entries);
var result = fileSystem.GetFile(service.HostsFilePath);
diff --git a/src/modules/Hosts/Hosts/Helpers/ExpressionExtensions.cs b/src/modules/Hosts/Hosts/Helpers/ExpressionExtensions.cs
new file mode 100644
index 0000000000..a72265ab24
--- /dev/null
+++ b/src/modules/Hosts/Hosts/Helpers/ExpressionExtensions.cs
@@ -0,0 +1,43 @@
+// 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.Linq.Expressions;
+
+namespace Hosts.Helpers
+{
+ // https://stackoverflow.com/a/22569086
+ public static class ExpressionExtensions
+ {
+ public static Expression> And(
+ this Expression> expr1,
+ Expression> expr2)
+ {
+ var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
+ return Expression.Lambda>(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
+ }
+
+ public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx)
+ {
+ return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
+ }
+
+ internal sealed class ReplaceVisitor : ExpressionVisitor
+ {
+ private readonly Expression _from;
+ private readonly Expression _to;
+
+ public ReplaceVisitor(Expression from, Expression to)
+ {
+ _from = from;
+ _to = to;
+ }
+
+ public override Expression Visit(Expression node)
+ {
+ return node == _from ? _to : base.Visit(node);
+ }
+ }
+ }
+}
diff --git a/src/modules/Hosts/Hosts/Helpers/HostsService.cs b/src/modules/Hosts/Hosts/Helpers/HostsService.cs
index 2e117446ad..7d90e57144 100644
--- a/src/modules/Hosts/Hosts/Helpers/HostsService.cs
+++ b/src/modules/Hosts/Hosts/Helpers/HostsService.cs
@@ -15,6 +15,7 @@ using System.Threading;
using System.Threading.Tasks;
using Hosts.Models;
using Hosts.Settings;
+using ManagedCommon;
using Microsoft.Win32;
using Settings.UI.Library.Enumerations;
@@ -82,7 +83,7 @@ namespace Hosts.Helpers
continue;
}
- var entry = new Entry(line);
+ var entry = new Entry(i, line);
if (entry.Valid)
{
diff --git a/src/modules/Hosts/Hosts/Helpers/Logger.cs b/src/modules/Hosts/Hosts/Helpers/Logger.cs
deleted file mode 100644
index 8a4cd558ce..0000000000
--- a/src/modules/Hosts/Hosts/Helpers/Logger.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.IO.Abstractions;
-using interop;
-
-namespace Hosts.Helpers
-{
- // TODO: use centralized logger https://github.com/microsoft/PowerToys/issues/19650
- public static class Logger
- {
- private static readonly IFileSystem _fileSystem = new FileSystem();
- private static readonly string ApplicationLogPath = Path.Combine(Constants.AppDataPath(), "Hosts\\Logs");
-
- static Logger()
- {
- if (!_fileSystem.Directory.Exists(ApplicationLogPath))
- {
- _fileSystem.Directory.CreateDirectory(ApplicationLogPath);
- }
-
- // Using InvariantCulture since this is used for a log file name
- var logFilePath = _fileSystem.Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
-
- Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
-
- Trace.AutoFlush = true;
- }
-
- public static void LogError(string message)
- {
- Log(message, "ERROR");
- }
-
- public static void LogError(string message, Exception ex)
- {
- Log(
- message + Environment.NewLine +
- ex?.Message + Environment.NewLine +
- "Inner exception: " + Environment.NewLine +
- ex?.InnerException?.Message + Environment.NewLine +
- "Stack trace: " + Environment.NewLine +
- ex?.StackTrace,
- "ERROR");
- }
-
- public static void LogWarning(string message)
- {
- Log(message, "WARNING");
- }
-
- public static void LogInfo(string message)
- {
- Log(message, "INFO");
- }
-
- private static void Log(string message, string type)
- {
- Trace.WriteLine(type + ": " + DateTime.Now.TimeOfDay);
- Trace.Indent();
- Trace.WriteLine(GetCallerInfo());
- Trace.WriteLine(message);
- Trace.Unindent();
- }
-
- private static string GetCallerInfo()
- {
- StackTrace stackTrace = new StackTrace();
-
- var methodName = stackTrace.GetFrame(3)?.GetMethod();
- var className = methodName?.DeclaringType.Name;
- return "[Method]: " + methodName?.Name + " [Class]: " + className;
- }
- }
-}
diff --git a/src/modules/Hosts/Hosts/Helpers/NativeMethods.cs b/src/modules/Hosts/Hosts/Helpers/NativeMethods.cs
index bff5f3db4f..9db941164b 100644
--- a/src/modules/Hosts/Hosts/Helpers/NativeMethods.cs
+++ b/src/modules/Hosts/Hosts/Helpers/NativeMethods.cs
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
namespace Hosts.Helpers
{
- internal class NativeMethods
+ internal sealed class NativeMethods
{
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);
diff --git a/src/modules/Hosts/Hosts/Hosts.csproj b/src/modules/Hosts/Hosts/Hosts.csproj
index 0baa5bf015..36e0ac4436 100644
--- a/src/modules/Hosts/Hosts/Hosts.csproj
+++ b/src/modules/Hosts/Hosts/Hosts.csproj
@@ -46,15 +46,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -64,6 +64,7 @@
+
diff --git a/src/modules/awake/Awake/Core/Models/BatteryReportingScale.cs b/src/modules/Hosts/Hosts/Models/AddressType.cs
similarity index 60%
rename from src/modules/awake/Awake/Core/Models/BatteryReportingScale.cs
rename to src/modules/Hosts/Hosts/Models/AddressType.cs
index 1520662e47..f89a950218 100644
--- a/src/modules/awake/Awake/Core/Models/BatteryReportingScale.cs
+++ b/src/modules/Hosts/Hosts/Models/AddressType.cs
@@ -2,11 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace Awake.Core.Models
+namespace Hosts.Models
{
- public struct BatteryReportingScale
+ public enum AddressType
{
- public uint Granularity;
- public uint Capacity;
+ Invalid = 0,
+ IPv4 = 1,
+ IPv6 = 2,
}
}
diff --git a/src/modules/Hosts/Hosts/Models/Entry.cs b/src/modules/Hosts/Hosts/Models/Entry.cs
index 11cebaeb73..23ce2518d6 100644
--- a/src/modules/Hosts/Hosts/Models/Entry.cs
+++ b/src/modules/Hosts/Hosts/Models/Entry.cs
@@ -22,6 +22,7 @@ namespace Hosts.Models
set
{
SetProperty(ref _address, value);
+ SetAddressType();
OnPropertyChanged(nameof(Valid));
}
}
@@ -54,22 +55,28 @@ namespace Hosts.Models
[ObservableProperty]
private bool _duplicate;
- public bool Valid => ValidationHelper.ValidHosts(_hosts) && (ValidationHelper.ValidIPv4(_address) || ValidationHelper.ValidIPv6(_address));
+ public bool Valid => ValidationHelper.ValidHosts(_hosts) && Type != AddressType.Invalid;
+
+ public AddressType Type { get; private set; }
public string[] SplittedHosts { get; private set; }
+ public int Id { get; set; }
+
public Entry()
{
}
- public Entry(string line)
+ public Entry(int id, string line)
{
+ Id = id;
_line = line.Trim();
Parse();
}
- public Entry(string address, string hosts, string comment, bool active)
+ public Entry(int id, string address, string hosts, string comment, bool active)
{
+ Id = id;
Address = address.Trim();
Hosts = hosts.Trim();
Comment = comment.Trim();
@@ -151,5 +158,21 @@ namespace Hosts.Models
{
return _line;
}
+
+ private void SetAddressType()
+ {
+ if (ValidationHelper.ValidIPv4(_address))
+ {
+ Type = AddressType.IPv4;
+ }
+ else if (ValidationHelper.ValidIPv6(_address))
+ {
+ Type = AddressType.IPv6;
+ }
+ else
+ {
+ Type = AddressType.Invalid;
+ }
+ }
}
}
diff --git a/src/modules/Hosts/Hosts/Program.cs b/src/modules/Hosts/Hosts/Program.cs
index 32b46a7a44..4b41f3c71a 100644
--- a/src/modules/Hosts/Hosts/Program.cs
+++ b/src/modules/Hosts/Hosts/Program.cs
@@ -4,7 +4,7 @@
using System;
using System.Threading;
-using Hosts.Helpers;
+using ManagedCommon;
using Microsoft.UI.Dispatching;
using Microsoft.Windows.AppLifecycle;
@@ -15,6 +15,8 @@ namespace Hosts
[STAThread]
public static void Main(string[] args)
{
+ Logger.InitializeLogger("\\Hosts\\Logs");
+
WinRT.ComWrappersSupport.InitializeComWrappers();
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredHostsFileEditorEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
diff --git a/src/modules/Hosts/Hosts/Settings/IUserSettings.cs b/src/modules/Hosts/Hosts/Settings/IUserSettings.cs
index 5278d60a95..1f1d97caa4 100644
--- a/src/modules/Hosts/Hosts/Settings/IUserSettings.cs
+++ b/src/modules/Hosts/Hosts/Settings/IUserSettings.cs
@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using Settings.UI.Library.Enumerations;
namespace Hosts.Settings
@@ -10,6 +11,10 @@ namespace Hosts.Settings
{
public bool ShowStartupWarning { get; }
+ public bool LoopbackDuplicates { get; }
+
public AdditionalLinesPosition AdditionalLinesPosition { get; }
+
+ event EventHandler LoopbackDuplicatesChanged;
}
}
diff --git a/src/modules/Hosts/Hosts/Settings/UserSettings.cs b/src/modules/Hosts/Hosts/Settings/UserSettings.cs
index 26a8e931e0..f1e47e6019 100644
--- a/src/modules/Hosts/Hosts/Settings/UserSettings.cs
+++ b/src/modules/Hosts/Hosts/Settings/UserSettings.cs
@@ -5,6 +5,7 @@
using System;
using System.IO.Abstractions;
using System.Threading;
+using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Settings.UI.Library.Enumerations;
@@ -22,12 +23,28 @@ namespace Hosts.Settings
public bool ShowStartupWarning { get; private set; }
+ private bool _loopbackDuplicates;
+
+ public bool LoopbackDuplicates
+ {
+ get => _loopbackDuplicates;
+ set
+ {
+ if (_loopbackDuplicates != value)
+ {
+ _loopbackDuplicates = value;
+ LoopbackDuplicatesChanged?.Invoke(this, EventArgs.Empty);
+ }
+ }
+ }
+
public AdditionalLinesPosition AdditionalLinesPosition { get; private set; }
public UserSettings()
{
_settingsUtils = new SettingsUtils();
ShowStartupWarning = true;
+ LoopbackDuplicates = false;
AdditionalLinesPosition = AdditionalLinesPosition.Top;
LoadSettingsFromJson();
@@ -35,6 +52,8 @@ namespace Hosts.Settings
_watcher = Helper.GetFileWatcher(HostsModuleName, "settings.json", () => LoadSettingsFromJson());
}
+ public event EventHandler LoopbackDuplicatesChanged;
+
private void LoadSettingsFromJson()
{
lock (_loadingSettingsLock)
@@ -60,6 +79,7 @@ namespace Hosts.Settings
{
ShowStartupWarning = settings.Properties.ShowStartupWarning;
AdditionalLinesPosition = settings.Properties.AdditionalLinesPosition;
+ LoopbackDuplicates = settings.Properties.LoopbackDuplicates;
}
retry = false;
diff --git a/src/modules/Hosts/Hosts/ViewModels/MainViewModel.cs b/src/modules/Hosts/Hosts/ViewModels/MainViewModel.cs
index 23bd229890..0896e9c115 100644
--- a/src/modules/Hosts/Hosts/ViewModels/MainViewModel.cs
+++ b/src/modules/Hosts/Hosts/ViewModels/MainViewModel.cs
@@ -6,14 +6,18 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Linq.Expressions;
+using System.Threading;
using System.Threading.Tasks;
-using System.Windows.Input;
using Common.UI;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI;
+using CommunityToolkit.WinUI.UI;
using Hosts.Helpers;
using Hosts.Models;
+using Hosts.Settings;
+using ManagedCommon;
using Microsoft.UI.Dispatching;
namespace Hosts.ViewModels
@@ -21,8 +25,18 @@ namespace Hosts.ViewModels
public partial class MainViewModel : ObservableObject, IDisposable
{
private readonly IHostsService _hostsService;
+ private readonly IUserSettings _userSettings;
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
+ private readonly string[] _loopbackAddresses =
+ {
+ "127.0.0.1",
+ "::1",
+ "0:0:0:0:0:0:0:1",
+ };
+
+ private bool _readingHosts;
private bool _disposed;
+ private CancellationTokenSource _tokenSource;
[ObservableProperty]
private Entry _selected;
@@ -33,9 +47,6 @@ namespace Hosts.ViewModels
[ObservableProperty]
private bool _fileChanged;
- [ObservableProperty]
- private bool _filtered;
-
[ObservableProperty]
private string _addressFilter;
@@ -46,34 +57,39 @@ namespace Hosts.ViewModels
private string _commentFilter;
[ObservableProperty]
- [NotifyPropertyChangedFor(nameof(Entries))]
- private bool _showOnlyDuplicates;
+ private string _additionalLines;
[ObservableProperty]
- private string _additionalLines;
+ private bool _isLoading;
+
+ [ObservableProperty]
+ private bool _filtered;
+
+ private bool _showOnlyDuplicates;
+
+ public bool ShowOnlyDuplicates
+ {
+ get => _showOnlyDuplicates;
+ set
+ {
+ SetProperty(ref _showOnlyDuplicates, value);
+ ApplyFilters();
+ }
+ }
private ObservableCollection _entries;
- public ObservableCollection Entries => _filtered || _showOnlyDuplicates ? GetFilteredEntries() : _entries;
+ public AdvancedCollectionView Entries { get; set; }
- public ICommand ReadHostsCommand => new RelayCommand(ReadHosts);
+ public int NextId => _entries.Max(e => e.Id) + 1;
- public ICommand ApplyFiltersCommand => new RelayCommand(ApplyFilters);
-
- public ICommand ClearFiltersCommand => new RelayCommand(ClearFilters);
-
- public ICommand OpenSettingsCommand => new RelayCommand(OpenSettings);
-
- public ICommand OpenHostsFileCommand => new RelayCommand(OpenHostsFile);
-
- public MainViewModel(IHostsService hostService)
+ public MainViewModel(IHostsService hostService, IUserSettings userSettings)
{
_hostsService = hostService;
+ _userSettings = userSettings;
- _hostsService.FileChanged += (s, e) =>
- {
- _dispatcherQueue.TryEnqueue(() => FileChanged = true);
- };
+ _hostsService.FileChanged += (s, e) => _dispatcherQueue.TryEnqueue(() => FileChanged = true);
+ _userSettings.LoopbackDuplicatesChanged += (s, e) => ReadHosts();
}
public void Add(Entry entry)
@@ -82,12 +98,11 @@ namespace Hosts.ViewModels
_entries.Add(entry);
FindDuplicates(entry.Address, entry.SplittedHosts);
- OnPropertyChanged(nameof(Entries));
}
public void Update(int index, Entry entry)
{
- var existingEntry = Entries.ElementAt(index);
+ var existingEntry = Entries[index] as Entry;
var oldAddress = existingEntry.Address;
var oldHosts = existingEntry.SplittedHosts;
@@ -98,7 +113,6 @@ namespace Hosts.ViewModels
FindDuplicates(oldAddress, oldHosts);
FindDuplicates(entry.Address, entry.SplittedHosts);
- OnPropertyChanged(nameof(Entries));
}
public void DeleteSelected()
@@ -108,7 +122,6 @@ namespace Hosts.ViewModels
_entries.Remove(Selected);
FindDuplicates(address, hosts);
- OnPropertyChanged(nameof(Entries));
}
public void UpdateAdditionalLines(string lines)
@@ -122,12 +135,39 @@ namespace Hosts.ViewModels
});
}
+ public void Move(int oldIndex, int newIndex)
+ {
+ if (Filtered)
+ {
+ return;
+ }
+
+ // Swap the IDs
+ var entry1 = _entries[oldIndex];
+ var entry2 = _entries[newIndex];
+ (entry2.Id, entry1.Id) = (entry1.Id, entry2.Id);
+
+ // Move entries in the UI
+ _entries.Move(oldIndex, newIndex);
+ }
+
+ [RelayCommand]
public void ReadHosts()
{
- FileChanged = false;
+ if (_readingHosts)
+ {
+ return;
+ }
+
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ FileChanged = false;
+ IsLoading = true;
+ });
Task.Run(async () =>
{
+ _readingHosts = true;
(_additionalLines, var entries) = await _hostsService.ReadAsync();
await _dispatcherQueue.EnqueueAsync(() =>
@@ -140,32 +180,66 @@ namespace Hosts.ViewModels
}
_entries.CollectionChanged += Entries_CollectionChanged;
+ Entries = new AdvancedCollectionView(_entries, true);
+ Entries.SortDescriptions.Add(new SortDescription(nameof(Entry.Id), SortDirection.Ascending));
+ ApplyFilters();
OnPropertyChanged(nameof(Entries));
- FindDuplicates();
+ IsLoading = false;
});
+ _readingHosts = false;
+
+ _tokenSource?.Cancel();
+ _tokenSource = new CancellationTokenSource();
+ FindDuplicates(_tokenSource.Token);
});
}
+ [RelayCommand]
public void ApplyFilters()
{
- if (_entries == null)
+ var expressions = new List>>(4);
+
+ if (!string.IsNullOrWhiteSpace(_addressFilter))
{
- return;
+ expressions.Add(e => ((Entry)e).Address.Contains(_addressFilter, StringComparison.OrdinalIgnoreCase));
}
- Filtered = !string.IsNullOrWhiteSpace(_addressFilter)
- || !string.IsNullOrWhiteSpace(_hostsFilter)
- || !string.IsNullOrWhiteSpace(_commentFilter);
+ if (!string.IsNullOrWhiteSpace(_hostsFilter))
+ {
+ expressions.Add(e => ((Entry)e).Hosts.Contains(_hostsFilter, StringComparison.OrdinalIgnoreCase));
+ }
- OnPropertyChanged(nameof(Entries));
+ if (!string.IsNullOrWhiteSpace(_commentFilter))
+ {
+ expressions.Add(e => ((Entry)e).Comment.Contains(_commentFilter, StringComparison.OrdinalIgnoreCase));
+ }
+
+ if (_showOnlyDuplicates)
+ {
+ expressions.Add(e => ((Entry)e).Duplicate);
+ }
+
+ Expression> filterExpression = null;
+
+ foreach (var e in expressions)
+ {
+ filterExpression = filterExpression == null ? e : filterExpression.And(e);
+ }
+
+ Filtered = filterExpression != null;
+ Entries.Filter = Filtered ? filterExpression.Compile().Invoke : null;
+ Entries.RefreshFilter();
}
+ [RelayCommand]
public void ClearFilters()
{
AddressFilter = null;
HostsFilter = null;
CommentFilter = null;
ShowOnlyDuplicates = false;
+ Entries.Filter = null;
+ Entries.RefreshFilter();
}
public async Task PingSelectedAsync()
@@ -177,11 +251,13 @@ namespace Hosts.ViewModels
selected.Pinging = false;
}
+ [RelayCommand]
public void OpenSettings()
{
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.Hosts);
}
+ [RelayCommand]
public void OpenHostsFile()
{
_hostsService.OpenHostsFile();
@@ -195,6 +271,14 @@ namespace Hosts.ViewModels
private void Entry_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
+ if (Filtered && (e.PropertyName == nameof(Entry.Hosts)
+ || e.PropertyName == nameof(Entry.Address)
+ || e.PropertyName == nameof(Entry.Comment)
+ || e.PropertyName == nameof(Entry.Duplicate)))
+ {
+ Entries.RefreshFilter();
+ }
+
// Ping and duplicate should't trigger a file save
if (e.PropertyName == nameof(Entry.Ping)
|| e.PropertyName == nameof(Entry.Pinging)
@@ -219,19 +303,34 @@ namespace Hosts.ViewModels
});
}
- private void FindDuplicates()
+ private void FindDuplicates(CancellationToken cancellationToken)
{
foreach (var entry in _entries)
{
- SetDuplicate(entry);
+ try
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (!_userSettings.LoopbackDuplicates && _loopbackAddresses.Contains(entry.Address))
+ {
+ continue;
+ }
+
+ SetDuplicate(entry);
+ }
+ catch (OperationCanceledException)
+ {
+ Logger.LogInfo("FindDuplicates cancelled");
+ return;
+ }
}
}
private void FindDuplicates(string address, IEnumerable hosts)
{
var entries = _entries.Where(e =>
- string.Equals(e.Address, address, StringComparison.InvariantCultureIgnoreCase)
- || hosts.Intersect(e.SplittedHosts, StringComparer.InvariantCultureIgnoreCase).Any());
+ string.Equals(e.Address, address, StringComparison.OrdinalIgnoreCase)
+ || hosts.Intersect(e.SplittedHosts, StringComparer.OrdinalIgnoreCase).Any());
foreach (var entry in entries)
{
@@ -241,44 +340,27 @@ namespace Hosts.ViewModels
private void SetDuplicate(Entry entry)
{
+ if (!_userSettings.LoopbackDuplicates && _loopbackAddresses.Contains(entry.Address))
+ {
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ entry.Duplicate = false;
+ });
+
+ return;
+ }
+
var hosts = entry.SplittedHosts;
- entry.Duplicate = _entries.FirstOrDefault(e =>
- e != entry
- && (string.Equals(e.Address, entry.Address, StringComparison.InvariantCultureIgnoreCase)
- || hosts.Intersect(e.SplittedHosts, StringComparer.InvariantCultureIgnoreCase).Any())) != null;
- }
+ var duplicate = _entries.FirstOrDefault(e => e != entry
+ && e.Type == entry.Type
+ && (string.Equals(e.Address, entry.Address, StringComparison.OrdinalIgnoreCase)
+ || hosts.Intersect(e.SplittedHosts, StringComparer.OrdinalIgnoreCase).Any())) != null;
- private ObservableCollection GetFilteredEntries()
- {
- if (_entries == null)
+ _dispatcherQueue.TryEnqueue(() =>
{
- return new ObservableCollection();
- }
-
- var filter = _entries.AsEnumerable();
-
- if (!string.IsNullOrWhiteSpace(_addressFilter))
- {
- filter = filter.Where(e => e.Address.Contains(_addressFilter, StringComparison.OrdinalIgnoreCase));
- }
-
- if (!string.IsNullOrWhiteSpace(_hostsFilter))
- {
- filter = filter.Where(e => e.Hosts.Contains(_hostsFilter, StringComparison.OrdinalIgnoreCase));
- }
-
- if (!string.IsNullOrWhiteSpace(_commentFilter))
- {
- filter = filter.Where(e => e.Comment.Contains(_commentFilter, StringComparison.OrdinalIgnoreCase));
- }
-
- if (_showOnlyDuplicates)
- {
- filter = filter.Where(e => e.Duplicate);
- }
-
- return new ObservableCollection(filter);
+ entry.Duplicate = duplicate;
+ });
}
protected virtual void Dispose(bool disposing)
diff --git a/src/modules/Hosts/Hosts/Views/MainPage.xaml b/src/modules/Hosts/Hosts/Views/MainPage.xaml
index 85aaabaa68..566af4feb5 100644
--- a/src/modules/Hosts/Hosts/Views/MainPage.xaml
+++ b/src/modules/Hosts/Hosts/Views/MainPage.xaml
@@ -26,6 +26,10 @@
NotEmptyValue="Visible" />
+
@@ -194,7 +198,8 @@
IsItemClickEnabled="True"
ItemClick="Entries_ItemClick"
ItemsSource="{Binding Entries, Mode=TwoWay}"
- SelectedItem="{Binding Selected, Mode=TwoWay}">
+ SelectedItem="{Binding Selected, Mode=TwoWay}"
+ Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource BoolToInvertedVisibilityConverter}, Mode=OneWay}">
+
+
0)
{
- ViewModel.Entries.Move(index, index - 1);
+ ViewModel.Move(index, index - 1);
}
}
}
@@ -179,7 +179,7 @@ namespace Hosts.Views
var index = ViewModel.Entries.IndexOf(entry);
if (index < ViewModel.Entries.Count - 1)
{
- ViewModel.Entries.Move(index, index + 1);
+ ViewModel.Move(index, index + 1);
}
}
}
diff --git a/src/modules/Hosts/Hosts/app.manifest b/src/modules/Hosts/Hosts/app.manifest
index 87a882d863..6417c11e2d 100644
--- a/src/modules/Hosts/Hosts/app.manifest
+++ b/src/modules/Hosts/Hosts/app.manifest
@@ -12,4 +12,10 @@
PerMonitorV2, PerMonitor
+
+
+
+
+
+
diff --git a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp b/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
index 8daa522b5d..aeb05ba2e6 100644
--- a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
+++ b/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
@@ -57,7 +57,7 @@ private:
void bring_process_to_front()
{
auto enum_windows = [](HWND hwnd, LPARAM param) -> BOOL {
- HANDLE process_handle = (HANDLE)param;
+ HANDLE process_handle = reinterpret_cast(param);
DWORD window_process_id = 0;
GetWindowThreadProcessId(hwnd, &window_process_id);
diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
index 047e418422..93f8a693d9 100644
--- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
+++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
@@ -1,8 +1,8 @@
+
-
true
true
@@ -143,21 +143,21 @@
-
+
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}.
-
-
+
+
\ No newline at end of file
diff --git a/src/modules/MeasureTool/MeasureToolCore/app.manifest b/src/modules/MeasureTool/MeasureToolCore/app.manifest
index 4aedd37014..1292107c7f 100644
--- a/src/modules/MeasureTool/MeasureToolCore/app.manifest
+++ b/src/modules/MeasureTool/MeasureToolCore/app.manifest
@@ -12,4 +12,10 @@
PerMonitorV2, PerMonitor
+
+
+
+
+
+
diff --git a/src/modules/MeasureTool/MeasureToolCore/packages.config b/src/modules/MeasureTool/MeasureToolCore/packages.config
index 9322bb3315..e52f75ad83 100644
--- a/src/modules/MeasureTool/MeasureToolCore/packages.config
+++ b/src/modules/MeasureTool/MeasureToolCore/packages.config
@@ -3,4 +3,5 @@
+
\ No newline at end of file
diff --git a/src/modules/MeasureTool/MeasureToolModuleInterface/dllmain.cpp b/src/modules/MeasureTool/MeasureToolModuleInterface/dllmain.cpp
index ac80a4a399..4148effdb1 100644
--- a/src/modules/MeasureTool/MeasureToolModuleInterface/dllmain.cpp
+++ b/src/modules/MeasureTool/MeasureToolModuleInterface/dllmain.cpp
@@ -3,9 +3,11 @@
#include
#include
#include "trace.h"
+#include
#include
#include
#include
+#include
extern "C" IMAGE_DOS_HEADER __ImageBase;
@@ -49,6 +51,9 @@ private:
Hotkey m_hotkey;
HANDLE m_hProcess;
+ HANDLE triggerEvent;
+ EventWaiter triggerEventWaiter;
+
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -142,6 +147,11 @@ public:
{
LoggerHelpers::init_logger(L"Measure Tool", L"ModuleInterface", "Measure Tool");
init_settings();
+
+ triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT);
+ triggerEventWaiter = EventWaiter(CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT, [this](int) {
+ on_hotkey(0);
+ });
}
~MeasureTool()
diff --git a/src/modules/MeasureTool/MeasureToolUI/App.xaml.cs b/src/modules/MeasureTool/MeasureToolUI/App.xaml.cs
index f81bc2047f..9cb26f54f5 100644
--- a/src/modules/MeasureTool/MeasureToolUI/App.xaml.cs
+++ b/src/modules/MeasureTool/MeasureToolUI/App.xaml.cs
@@ -4,7 +4,6 @@
using System;
using ManagedCommon;
-using MeasureToolUI.Helpers;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
@@ -22,6 +21,8 @@ namespace MeasureToolUI
///
public App()
{
+ Logger.InitializeLogger("\\Measure Tool\\MeasureToolUI\\Logs");
+
this.InitializeComponent();
}
diff --git a/src/modules/MeasureTool/MeasureToolUI/Logger.cs b/src/modules/MeasureTool/MeasureToolUI/Logger.cs
deleted file mode 100644
index 30fb1b43a4..0000000000
--- a/src/modules/MeasureTool/MeasureToolUI/Logger.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-
-namespace MeasureToolUI.Helpers
-{
- public static class Logger
- {
- private static readonly string ApplicationLogPath = Path.Combine(interop.Constants.AppDataPath(), "Measure Tool\\MeasureToolUI\\Logs");
-
- static Logger()
- {
- if (!Directory.Exists(ApplicationLogPath))
- {
- Directory.CreateDirectory(ApplicationLogPath);
- }
-
- // Using InvariantCulture since this is used for a log file name
- var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
-
- Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
-
- Trace.AutoFlush = true;
- }
-
- public static void LogError(string message)
- {
- Log(message, "ERROR");
- }
-
- public static void LogError(string message, Exception ex)
- {
- Log(
- message + Environment.NewLine +
- ex?.Message + Environment.NewLine +
- "Inner exception: " + Environment.NewLine +
- ex?.InnerException?.Message + Environment.NewLine +
- "Stack trace: " + Environment.NewLine +
- ex?.StackTrace,
- "ERROR");
- }
-
- public static void LogWarning(string message)
- {
- Log(message, "WARNING");
- }
-
- public static void LogInfo(string message)
- {
- Log(message, "INFO");
- }
-
- private static void Log(string message, string type)
- {
- Trace.WriteLine(type + ": " + DateTime.Now.TimeOfDay);
- Trace.Indent();
- Trace.WriteLine(GetCallerInfo());
- Trace.WriteLine(message);
- Trace.Unindent();
- }
-
- private static string GetCallerInfo()
- {
- StackTrace stackTrace = new StackTrace();
-
- var methodName = stackTrace.GetFrame(3)?.GetMethod();
- var className = methodName?.DeclaringType.Name;
- return "[Method]: " + methodName?.Name + " [Class]: " + className;
- }
- }
-}
diff --git a/src/modules/MeasureTool/MeasureToolUI/MainWindow.xaml b/src/modules/MeasureTool/MeasureToolUI/MainWindow.xaml
index d787abb492..973781a777 100644
--- a/src/modules/MeasureTool/MeasureToolUI/MainWindow.xaml
+++ b/src/modules/MeasureTool/MeasureToolUI/MainWindow.xaml
@@ -5,8 +5,8 @@
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:p="using:PowerToys.MeasureToolUI.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:p="using:PowerToys.MeasureToolUI.Properties"
xmlns:winuiex="using:WinUIEx"
IsAlwaysOnTop="True"
IsMaximizable="False"
diff --git a/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj b/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj
index c43cda95ed..96d510e7b9 100644
--- a/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj
+++ b/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj
@@ -69,10 +69,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/modules/MeasureTool/MeasureToolUI/app.manifest b/src/modules/MeasureTool/MeasureToolUI/app.manifest
index ba6d50bdd8..908d7af1a8 100644
--- a/src/modules/MeasureTool/MeasureToolUI/app.manifest
+++ b/src/modules/MeasureTool/MeasureToolUI/app.manifest
@@ -12,4 +12,10 @@
PerMonitorV2, PerMonitor
+
+
+
+
+
+
diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
index d03e91c684..4c84691095 100644
--- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
+++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
@@ -161,7 +161,7 @@ bool SuperSonar::Initialize(HINSTANCE hinst)
wc.hInstance = hinst;
wc.hIcon = LoadIcon(hinst, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
+ wc.hbrBackground = static_cast(GetStockObject(NULL_BRUSH));
wc.lpszClassName = className;
if (!RegisterClassW(&wc))
@@ -196,14 +196,14 @@ LRESULT SuperSonar::s_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
SuperSonar* self;
if (message == WM_NCCREATE)
{
- auto info = (LPCREATESTRUCT)lParam;
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)info->lpCreateParams);
- self = (SuperSonar*)info->lpCreateParams;
+ auto info = reinterpret_cast(lParam);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(info->lpCreateParams));
+ self = static_cast(info->lpCreateParams);
self->m_hwnd = hwnd;
}
else
{
- self = (SuperSonar*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ self = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
if (self)
{
@@ -230,7 +230,7 @@ LRESULT SuperSonar::BaseWndProc(UINT message, WPARAM wParam, LPARAM lParam) n
break;
case WM_INPUT:
- OnSonarInput(wParam, (HRAWINPUT)lParam);
+ OnSonarInput(wParam, reinterpret_cast(lParam));
break;
case WM_TIMER:
@@ -272,7 +272,7 @@ void SuperSonar::OnSonarInput(WPARAM flags, HRAWINPUT hInput)
RAWINPUT input;
UINT size = sizeof(input);
auto result = GetRawInputData(hInput, RID_INPUT, &input, &size, sizeof(RAWINPUTHEADER));
- if ((int)result < sizeof(RAWINPUTHEADER))
+ if (result < sizeof(RAWINPUTHEADER))
{
return;
}
@@ -397,7 +397,7 @@ void SuperSonar::DetectShake()
{
currentX += movement.diff.x;
currentY += movement.diff.y;
- distanceTravelled += sqrt((double)movement.diff.x * movement.diff.x + (double)movement.diff.y * movement.diff.y); // Pythagorean theorem
+ distanceTravelled += sqrt(static_cast(movement.diff.x) * movement.diff.x + static_cast(movement.diff.y) * movement.diff.y); // Pythagorean theorem
minX = min(currentX, minX);
maxX = max(currentX, maxX);
minY = min(currentY, minY);
@@ -410,8 +410,8 @@ void SuperSonar::DetectShake()
}
// Size of the rectangle the pointer moved in.
- double rectangleWidth = (double)maxX - minX;
- double rectangleHeight = (double)maxY - minY;
+ double rectangleWidth = static_cast(maxX) - minX;
+ double rectangleHeight = static_cast(maxY) - minY;
double diagonal = sqrt(rectangleWidth * rectangleWidth + rectangleHeight * rectangleHeight);
if (diagonal > 0 && distanceTravelled / diagonal > ShakeFactor)
@@ -592,7 +592,7 @@ bool SuperSonar::IsForegroundAppExcluded()
if (HWND foregroundApp{ GetForegroundWindow() })
{
auto processPath = get_process_path(foregroundApp);
- CharUpperBuffW(processPath.data(), (DWORD)processPath.length());
+ CharUpperBuffW(processPath.data(), static_cast(processPath.length()));
return find_app_name_in_path(processPath, m_excludedApps);
}
else
@@ -613,7 +613,7 @@ struct CompositionSpotlight : SuperSonar
void AfterMoveSonar()
{
- m_spotlight.Offset({ (float)m_sonarPos.x, (float)m_sonarPos.y, 0.0f });
+ m_spotlight.Offset({ static_cast(m_sonarPos.x), static_cast(m_sonarPos.y), 0.0f });
}
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
@@ -924,10 +924,10 @@ struct GdiSpotlight : GdiSonar
auto spotlight = CreateRoundRectRgn(
this->m_sonarPos.x - radius, this->m_sonarPos.y - radius, this->m_sonarPos.x + radius, this->m_sonarPos.y + radius, radius * 2, radius * 2);
- FillRgn(ps.hdc, spotlight, (HBRUSH)GetStockObject(WHITE_BRUSH));
+ FillRgn(ps.hdc, spotlight, static_cast(GetStockObject(WHITE_BRUSH)));
Sleep(1000 / 60);
ExtSelectClipRgn(ps.hdc, spotlight, RGN_DIFF);
- FillRect(ps.hdc, &ps.rcPaint, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ FillRect(ps.hdc, &ps.rcPaint, static_cast(GetStockObject(BLACK_BRUSH)));
DeleteObject(spotlight);
EndPaint(this->m_hwnd, &ps);
@@ -959,7 +959,7 @@ struct GdiCrosshairs : GdiSonar
auto radius = CurrentSonarRadius();
RECT rc;
- HBRUSH white = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ HBRUSH white = static_cast(GetStockObject(WHITE_BRUSH));
rc.left = m_sonarPos.x - radius;
rc.top = ps.rcPaint.top;
@@ -973,7 +973,7 @@ struct GdiCrosshairs : GdiSonar
rc.bottom = m_sonarPos.y + radius;
FillRect(ps.hdc, &rc, white);
- HBRUSH black = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ HBRUSH black = static_cast(GetStockObject(BLACK_BRUSH));
// Top left
rc.left = ps.rcPaint.left;
diff --git a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
index 27d809d07d..0241a8922b 100644
--- a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
+++ b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp
@@ -185,11 +185,16 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Activation Method
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_METHOD);
- UINT value = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
- if (value < (int)FindMyMouseActivationMethod::EnumElements)
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value < static_cast(FindMyMouseActivationMethod::EnumElements) && value >= 0)
{
- findMyMouseSettings.activationMethod = (FindMyMouseActivationMethod)value;
+ findMyMouseSettings.activationMethod = static_cast(value);
}
+ else
+ {
+ throw;
+ }
+
}
catch (...)
{
@@ -198,7 +203,7 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
try
{
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE);
- findMyMouseSettings.doNotActivateOnGameMode = (bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE);
+ findMyMouseSettings.doNotActivateOnGameMode = jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE);
}
catch (...)
{
@@ -246,7 +251,15 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Overlay Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_OVERLAY_OPACITY);
- findMyMouseSettings.overlayOpacity = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ findMyMouseSettings.overlayOpacity = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -256,7 +269,15 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Spotlight Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_RADIUS);
- findMyMouseSettings.spotlightRadius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ findMyMouseSettings.spotlightRadius = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -266,7 +287,15 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Animation Duration
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ANIMATION_DURATION_MS);
- findMyMouseSettings.animationDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ findMyMouseSettings.animationDurationMs = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -276,7 +305,15 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Spotlight Initial Zoom
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_INITIAL_ZOOM);
- findMyMouseSettings.spotlightInitialZoom = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ findMyMouseSettings.spotlightInitialZoom = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -289,7 +326,7 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
std::wstring apps = jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE).c_str();
std::vector excludedApps;
auto excludedUppercase = apps;
- CharUpperBuffW(excludedUppercase.data(), (DWORD)excludedUppercase.length());
+ CharUpperBuffW(excludedUppercase.data(), static_cast(excludedUppercase.length()));
std::wstring_view view(excludedUppercase);
view = left_trim(trim(view));
@@ -311,7 +348,15 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// Parse Shaking Minimum Distance
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHAKING_MINIMUM_DISTANCE);
- findMyMouseSettings.shakeMinimumDistance = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ findMyMouseSettings.shakeMinimumDistance = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
diff --git a/src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp b/src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp
index f1107db483..2a10ff648d 100644
--- a/src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp
+++ b/src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp
@@ -132,7 +132,7 @@ void Highlighter::AddDrawingPoint(MouseButton button)
auto circleGeometry = m_compositor.CreateEllipseGeometry();
circleGeometry.Radius({ m_radius, m_radius });
auto circleShape = m_compositor.CreateSpriteShape(circleGeometry);
- circleShape.Offset({ (float)pt.x, (float)pt.y });
+ circleShape.Offset({ static_cast(pt.x), static_cast(pt.y )});
if (button == MouseButton::Left)
{
circleShape.FillBrush(m_compositor.CreateColorBrush(m_leftClickColor));
@@ -166,12 +166,12 @@ void Highlighter::UpdateDrawingPointPosition(MouseButton button)
if (button == MouseButton::Left)
{
- m_leftPointer.Offset({ (float)pt.x, (float)pt.y });
+ m_leftPointer.Offset({ static_cast(pt.x), static_cast(pt.y )});
}
else
{
//right
- m_rightPointer.Offset({ (float)pt.x, (float)pt.y });
+ m_rightPointer.Offset({ static_cast(pt.x), static_cast(pt.y )});
}
}
void Highlighter::StartDrawingPointFading(MouseButton button)
@@ -217,7 +217,7 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
{
if (nCode >= 0)
{
- MSLLHOOKSTRUCT* hookData = (MSLLHOOKSTRUCT*)lParam;
+ MSLLHOOKSTRUCT* hookData = reinterpret_cast(lParam);
switch (wParam)
{
case WM_LBUTTONDOWN:
@@ -293,7 +293,7 @@ void Highlighter::SwitchActivationMode()
}
void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
- m_radius = (float)settings.radius;
+ m_radius = static_cast(settings.radius);
m_fadeDelay_ms = settings.fadeDelayMs;
m_fadeDuration_ms = settings.fadeDurationMs;
m_leftClickColor = settings.leftButtonColor;
@@ -349,7 +349,7 @@ bool Highlighter::MyRegisterClass(HINSTANCE hInstance)
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
+ wc.hbrBackground = static_cast(GetStockObject(NULL_BRUSH));
wc.lpszClassName = m_className;
if (!RegisterClassW(&wc))
diff --git a/src/modules/MouseUtils/MouseHighlighter/dllmain.cpp b/src/modules/MouseUtils/MouseHighlighter/dllmain.cpp
index 75cf746a02..b3860a227b 100644
--- a/src/modules/MouseUtils/MouseHighlighter/dllmain.cpp
+++ b/src/modules/MouseUtils/MouseHighlighter/dllmain.cpp
@@ -215,7 +215,15 @@ public:
{
// Parse Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_OPACITY);
- opacity = (uint8_t)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ opacity = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -234,7 +242,7 @@ public:
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_LEFT_BUTTON_CLICK_COLOR);
auto leftColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
- if (!checkValidRGB(leftColor,&r,&g,&b))
+ if (!checkValidRGB(leftColor, &r, &g, &b))
{
Logger::error("Left click color RGB value is invalid. Will use default value");
}
@@ -270,7 +278,15 @@ public:
{
// Parse Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_RADIUS);
- highlightSettings.radius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ highlightSettings.radius = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -280,7 +296,15 @@ public:
{
// Parse Fade Delay
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DELAY_MS);
- highlightSettings.fadeDelayMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ highlightSettings.fadeDelayMs = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
@@ -290,7 +314,15 @@ public:
{
// Parse Fade Duration
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DURATION_MS);
- highlightSettings.fadeDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
+ int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE));
+ if (value >= 0)
+ {
+ highlightSettings.fadeDurationMs = value;
+ }
+ else
+ {
+ throw;
+ }
}
catch (...)
{
diff --git a/src/modules/MouseUtils/MouseJump/MouseJump.rc b/src/modules/MouseUtils/MouseJump/MouseJump.rc
new file mode 100644
index 0000000000..f8d0a54cda
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/MouseJump.rc
@@ -0,0 +1,40 @@
+#include
+#include "resource.h"
+#include "../../../common/version/version.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+#include "winres.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+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
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj b/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
new file mode 100644
index 0000000000..16b9692ffd
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ 15.0
+ {8a08d663-4995-40e3-b42c-3f910625f284}
+ Win32Proj
+ MouseJumpModuleInterface
+ MouseJump
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\
+ PowerToys.MouseJump
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ Disabled
+ true
+ _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+ stdcpplatest
+
+
+ Windows
+ true
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+ stdcpplatest
+
+
+ Windows
+ true
+ true
+ true
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ $(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)
+
+
+
+
+ Use
+ pch.h
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+ {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
+
+
+ {6955446d-23f7-4023-9bb3-8657f904af99}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/dllmain.cpp b/src/modules/MouseUtils/MouseJump/dllmain.cpp
new file mode 100644
index 0000000000..4be0abdc48
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/dllmain.cpp
@@ -0,0 +1,302 @@
+#include "pch.h"
+
+#include
+//#include
+//#include
+#include
+#include "trace.h"
+#include
+#include
+
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+
+HMODULE m_hModule;
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
+{
+ m_hModule = hModule;
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ Trace::RegisterProvider();
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ Trace::UnregisterProvider();
+ break;
+ }
+ return TRUE;
+}
+
+// The PowerToy name that will be shown in the settings.
+const static wchar_t* MODULE_NAME = L"MouseJump";
+// Add a description that will we shown in the module settings page.
+const static wchar_t* MODULE_DESC = L"Quickly move the mouse long distances";
+
+namespace
+{
+ const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
+ const wchar_t JSON_KEY_WIN[] = L"win";
+ const wchar_t JSON_KEY_ALT[] = L"alt";
+ const wchar_t JSON_KEY_CTRL[] = L"ctrl";
+ const wchar_t JSON_KEY_SHIFT[] = L"shift";
+ const wchar_t JSON_KEY_CODE[] = L"code";
+ const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut";
+}
+
+// Implement the PowerToy Module Interface and all the required methods.
+class MouseJump : public PowertoyModuleIface
+{
+private:
+ // The PowerToy state.
+ bool m_enabled = false;
+
+ // Hotkey to invoke the module
+ Hotkey m_hotkey;
+ HANDLE m_hProcess;
+
+ void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
+ {
+ auto settingsObject = settings.get_raw_json();
+ if (settingsObject.GetView().Size())
+ {
+ try
+ {
+ auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
+ m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN);
+ m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT);
+ m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT);
+ m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL);
+ m_hotkey.key = static_cast(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE));
+ }
+ catch (...)
+ {
+ Logger::error("Failed to initialize Mouse Jump start shortcut");
+ }
+ }
+ else
+ {
+ Logger::info("MouseJump settings are empty");
+ }
+
+ if (!m_hotkey.key)
+ {
+ Logger::info("MouseJump is going to use default shortcut");
+ m_hotkey.win = true;
+ m_hotkey.alt = false;
+ m_hotkey.shift = true;
+ m_hotkey.ctrl = false;
+ m_hotkey.key = 'D';
+ }
+ }
+
+ bool is_process_running()
+ {
+ return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
+ }
+
+ void launch_process()
+ {
+ Logger::trace(L"Starting MouseJump process");
+ unsigned long powertoys_pid = GetCurrentProcessId();
+
+ std::wstring executable_args = L"";
+ executable_args.append(std::to_wstring(powertoys_pid));
+
+ SHELLEXECUTEINFOW sei{ sizeof(sei) };
+ sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
+ sei.lpFile = L"modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.exe";
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpParameters = executable_args.data();
+ if (ShellExecuteExW(&sei))
+ {
+ Logger::trace("Successfully started the Mouse Jump process");
+ }
+ else
+ {
+ Logger::error(L"Mouse Jump failed to start. {}", get_last_error_or_default(GetLastError()));
+ }
+
+ m_hProcess = sei.hProcess;
+ }
+
+ // Load initial settings from the persisted values.
+ void init_settings();
+
+ void terminate_process()
+ {
+ TerminateProcess(m_hProcess, 1);
+ }
+
+public:
+ // Constructor
+ MouseJump()
+ {
+ LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseJumpLoggerName);
+ init_settings();
+ };
+
+ ~MouseJump()
+ {
+ if (m_enabled)
+ {
+ terminate_process();
+ }
+ m_enabled = false;
+ }
+
+ // Destroy the powertoy and free memory
+ virtual void destroy() override
+ {
+ delete this;
+ }
+
+ // Return the display name of the powertoy, this will be cached by the runner
+ virtual const wchar_t* get_name() override
+ {
+ return MODULE_NAME;
+ }
+
+ // Return the non localized key of the powertoy, this will be cached by the runner
+ virtual const wchar_t* get_key() override
+ {
+ return MODULE_NAME;
+ }
+
+ // Return the configured status for the gpo policy for the module
+ virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
+ {
+ return powertoys_gpo::getConfiguredMouseJumpEnabledValue();
+ }
+
+ // Return JSON with the configuration options.
+ virtual bool get_config(wchar_t* buffer, int* buffer_size) override
+ {
+ HINSTANCE hinstance = reinterpret_cast(&__ImageBase);
+
+ // Create a Settings object.
+ PowerToysSettings::Settings settings(hinstance, get_name());
+ settings.set_description(MODULE_DESC);
+
+ return settings.serialize_to_buffer(buffer, buffer_size);
+ }
+
+ // Signal from the Settings editor to call a custom action.
+ // This can be used to spawn more complex editors.
+ virtual void call_custom_action(const wchar_t* action) override
+ {
+ }
+
+ // Called by the runner to pass the updated settings values as a serialized JSON.
+ virtual void set_config(const wchar_t* config) override
+ {
+ try
+ {
+ // Parse the input JSON string.
+ PowerToysSettings::PowerToyValues values =
+ PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
+
+ parse_hotkey(values);
+
+ values.save_to_settings_file();
+ }
+ catch (std::exception&)
+ {
+ // Improper JSON.
+ }
+ }
+
+ // Enable the powertoy
+ virtual void enable()
+ {
+ m_enabled = true;
+ Trace::EnableJumpTool(true);
+ }
+
+ // Disable the powertoy
+ virtual void disable()
+ {
+ if (m_enabled)
+ {
+ terminate_process();
+ }
+
+ m_enabled = false;
+ Trace::EnableJumpTool(false);
+ }
+
+ // Returns if the powertoys is enabled
+ virtual bool is_enabled() override
+ {
+ return m_enabled;
+ }
+
+ virtual bool on_hotkey(size_t /*hotkeyId*/) override
+ {
+ if (m_enabled)
+ {
+ Logger::trace(L"MouseJump hotkey pressed");
+ Trace::InvokeJumpTool();
+ if (is_process_running())
+ {
+ terminate_process();
+ }
+ launch_process();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
+ {
+ if (m_hotkey.key)
+ {
+ if (hotkeys && buffer_size >= 1)
+ {
+ hotkeys[0] = m_hotkey;
+ }
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // Returns whether the PowerToys should be enabled by default
+ virtual bool is_enabled_by_default() const override
+ {
+ return false;
+ }
+
+};
+
+// Load the settings file.
+void MouseJump::init_settings()
+{
+ try
+ {
+ // Load and parse the settings file for this PowerToy.
+ PowerToysSettings::PowerToyValues settings =
+ PowerToysSettings::PowerToyValues::load_from_settings_file(MouseJump::get_name());
+
+ parse_hotkey(settings);
+
+ }
+ catch (std::exception&)
+ {
+ Logger::warn(L"An exception occurred while loading the settings file");
+ // Error while loading from the settings file. Let default values stay as they are.
+ }
+}
+
+
+extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
+{
+ return new MouseJump();
+}
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/packages.config b/src/modules/MouseUtils/MouseJump/packages.config
new file mode 100644
index 0000000000..48319b8c95
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/pch.cpp b/src/modules/MouseUtils/MouseJump/pch.cpp
new file mode 100644
index 0000000000..1d9f38c57d
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/src/modules/MouseUtils/MouseJump/pch.h b/src/modules/MouseUtils/MouseJump/pch.h
new file mode 100644
index 0000000000..74abb62da1
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/pch.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+//#include
+#include
+#include
+#include
diff --git a/src/modules/MouseUtils/MouseJump/resource.h b/src/modules/MouseUtils/MouseJump/resource.h
new file mode 100644
index 0000000000..67b823fd7f
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/resource.h
@@ -0,0 +1,13 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MeasureTool.rc
+
+//////////////////////////////
+// Non-localizable
+
+#define FILE_DESCRIPTION "PowerToys MouseJump"
+#define INTERNAL_NAME "PowerToys.MouseJump"
+#define ORIGINAL_FILENAME "PowerToys.MouseJump.dll"
+
+// Non-localizable
+//////////////////////////////
diff --git a/src/modules/MouseUtils/MouseJump/trace.cpp b/src/modules/MouseUtils/MouseJump/trace.cpp
new file mode 100644
index 0000000000..9f5380284d
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/trace.cpp
@@ -0,0 +1,38 @@
+#include "pch.h"
+#include "trace.h"
+
+TRACELOGGING_DEFINE_PROVIDER(
+ g_hProvider,
+ "Microsoft.PowerToys",
+ // {38e8889b-9731-53f5-e901-e8a7c1753074}
+ (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
+ TraceLoggingOptionProjectTelemetry());
+
+void Trace::RegisterProvider()
+{
+ TraceLoggingRegister(g_hProvider);
+}
+
+void Trace::UnregisterProvider()
+{
+ TraceLoggingUnregister(g_hProvider);
+}
+
+void Trace::EnableJumpTool(const bool enabled) noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "MouseJump_EnableJumpTool",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
+ TraceLoggingBoolean(enabled, "Enabled"));
+}
+
+void Trace::InvokeJumpTool() noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "MouseJump_InvokeJumpTool",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
+}
diff --git a/src/modules/MouseUtils/MouseJump/trace.h b/src/modules/MouseUtils/MouseJump/trace.h
new file mode 100644
index 0000000000..aaaa336291
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/trace.h
@@ -0,0 +1,12 @@
+#pragma once
+
+class Trace
+{
+public:
+ static void RegisterProvider();
+ static void UnregisterProvider();
+
+ static void EnableJumpTool(const bool enabled) noexcept;
+
+ static void InvokeJumpTool() noexcept;
+};
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/DrawingHelperTests.cs b/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/DrawingHelperTests.cs
new file mode 100644
index 0000000000..7579780ebc
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/DrawingHelperTests.cs
@@ -0,0 +1,229 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MouseJumpUI.Helpers;
+using MouseJumpUI.Models.Drawing;
+using MouseJumpUI.Models.Layout;
+using MouseJumpUI.Models.Screen;
+using static MouseJumpUI.NativeMethods.Core;
+
+namespace MouseJumpUI.UnitTests.Helpers;
+
+[TestClass]
+public static class DrawingHelperTests
+{
+ [TestClass]
+ public sealed class CalculateLayoutInfoTests
+ {
+ public sealed class TestCase
+ {
+ public TestCase(LayoutConfig layoutConfig, LayoutInfo expectedResult)
+ {
+ this.LayoutConfig = layoutConfig;
+ this.ExpectedResult = expectedResult;
+ }
+
+ public LayoutConfig LayoutConfig { get; set; }
+
+ public LayoutInfo ExpectedResult { get; set; }
+ }
+
+ public static IEnumerable