mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-07 20:00:15 +01:00
Compare commits
82 Commits
dev/migrie
...
feature/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33ce801a56 | ||
|
|
0c4b30eb44 | ||
|
|
16937cf2af | ||
|
|
032e3d5dee | ||
|
|
54801f09f1 | ||
|
|
29587e48e7 | ||
|
|
c2fe908e18 | ||
|
|
d55fc53884 | ||
|
|
cf0a0d7ca9 | ||
|
|
139815ceb3 | ||
|
|
9311ac2579 | ||
|
|
b27e1081ae | ||
|
|
39869bcaae | ||
|
|
fb17678b01 | ||
|
|
315824f4ef | ||
|
|
36907ad6f2 | ||
|
|
8bacded9c4 | ||
|
|
5a3ccb3b60 | ||
|
|
00529713fd | ||
|
|
e0868b099a | ||
|
|
182e521730 | ||
|
|
797bd4cb35 | ||
|
|
297c7f0cbc | ||
|
|
7df1c2f002 | ||
|
|
8727a72a83 | ||
|
|
a2e81dbc3f | ||
|
|
7c870d48ea | ||
|
|
3006cbf42d | ||
|
|
a7ea40749e | ||
|
|
94ea7597be | ||
|
|
3f6b41fc80 | ||
|
|
aede049596 | ||
|
|
5440699250 | ||
|
|
57957d5dbf | ||
|
|
6e882b9cb2 | ||
|
|
ce24d9d951 | ||
|
|
3ee8a78178 | ||
|
|
d0b46a98eb | ||
|
|
3c08019190 | ||
|
|
25badc45a4 | ||
|
|
6b8a2064ab | ||
|
|
14d8c36768 | ||
|
|
23500371b5 | ||
|
|
f932679911 | ||
|
|
81494b23bf | ||
|
|
1ad1c98c98 | ||
|
|
ec9071bc4f | ||
|
|
180d4a21aa | ||
|
|
9a77b8e9cb | ||
|
|
b1935ca1eb | ||
|
|
a1c34b1503 | ||
|
|
5368c82154 | ||
|
|
c21ab5bc30 | ||
|
|
b3a084db0a | ||
|
|
4fe880cc1e | ||
|
|
e9cf9113a4 | ||
|
|
2752054b14 | ||
|
|
f7a30212d9 | ||
|
|
9b36bb9ddd | ||
|
|
79515f0d6b | ||
|
|
99523fe317 | ||
|
|
5398c16456 | ||
|
|
123d318d6a | ||
|
|
09a79ab692 | ||
|
|
9cd23666d3 | ||
|
|
bf99a2a0e5 | ||
|
|
261381f2f7 | ||
|
|
b971d8799a | ||
|
|
0155bb3b63 | ||
|
|
43e9959df4 | ||
|
|
231f59c7a9 | ||
|
|
1532dd5b38 | ||
|
|
9afa3a1ecc | ||
|
|
17af826408 | ||
|
|
b9c9ade9d9 | ||
|
|
18c335397f | ||
|
|
6d1f533af4 | ||
|
|
6dd9617538 | ||
|
|
d1564b0572 | ||
|
|
2ddf561f57 | ||
|
|
6fea4d9c5d | ||
|
|
77a8555fd4 |
@@ -1 +0,0 @@
|
||||
../.github/copilot-instructions.md
|
||||
@@ -1 +0,0 @@
|
||||
../.github/agents
|
||||
@@ -1 +0,0 @@
|
||||
../.github/prompts
|
||||
@@ -1 +0,0 @@
|
||||
../.github/instructions
|
||||
@@ -1 +0,0 @@
|
||||
../.github/skills
|
||||
1
.github/actions/spell-check/allow/names.txt
vendored
1
.github/actions/spell-check/allow/names.txt
vendored
@@ -206,7 +206,6 @@ Bilibili
|
||||
BVID
|
||||
capturevideosample
|
||||
cmdow
|
||||
Contoso
|
||||
Controlz
|
||||
cortana
|
||||
devhints
|
||||
|
||||
63
.github/actions/spell-check/allow/zoomit.txt
vendored
63
.github/actions/spell-check/allow/zoomit.txt
vendored
@@ -1,63 +0,0 @@
|
||||
acq
|
||||
APPLYTOSUBMENUS
|
||||
AUDCLNT
|
||||
bitmaps
|
||||
BUFFERFLAGS
|
||||
centiseconds
|
||||
Ctl
|
||||
CTLCOLOR
|
||||
CTLCOLORBTN
|
||||
CTLCOLORDLG
|
||||
CTLCOLOREDIT
|
||||
CTLCOLORLISTBOX
|
||||
CTrim
|
||||
DFCS
|
||||
dlg
|
||||
dlu
|
||||
DONTCARE
|
||||
DRAWITEM
|
||||
DRAWITEMSTRUCT
|
||||
DWLP
|
||||
EDITCONTROL
|
||||
ENABLEHOOK
|
||||
FDE
|
||||
GETCHANNELRECT
|
||||
GETCHECK
|
||||
GETTHUMBRECT
|
||||
GIFs
|
||||
HTBOTTOMRIGHT
|
||||
HTHEME
|
||||
KSDATAFORMAT
|
||||
LEFTNOWORDWRAP
|
||||
letterbox
|
||||
lld
|
||||
logfont
|
||||
lround
|
||||
MENUINFO
|
||||
mic
|
||||
MMRESULT
|
||||
OWNERDRAW
|
||||
PBGRA
|
||||
pfdc
|
||||
playhead
|
||||
pwfx
|
||||
quantums
|
||||
REFKNOWNFOLDERID
|
||||
reposted
|
||||
SCROLLSIZEGRIP
|
||||
SETDEFID
|
||||
SETRECT
|
||||
SHAREMODE
|
||||
SHAREVIOLATION
|
||||
STREAMFLAGS
|
||||
submix
|
||||
tci
|
||||
TEXTMETRIC
|
||||
tme
|
||||
TRACKMOUSEEVENT
|
||||
Unadvise
|
||||
WASAPI
|
||||
WAVEFORMATEX
|
||||
WAVEFORMATEXTENSIBLE
|
||||
wil
|
||||
WMU
|
||||
@@ -31,82 +31,59 @@
|
||||
"Common.Search.dll",
|
||||
|
||||
"PowerToys.AlwaysOnTop.exe",
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
|
||||
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
"PowerToys.ColorPickerUI.exe",
|
||||
|
||||
"PowerToys.CropAndLockModuleInterface.dll",
|
||||
"PowerToys.CropAndLock.exe",
|
||||
|
||||
"PowerToys.PowerOCRModuleInterface.dll",
|
||||
"PowerToys.PowerOCR.dll",
|
||||
"PowerToys.PowerOCR.exe",
|
||||
|
||||
"PowerToys.AdvancedPasteModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
|
||||
|
||||
"PowerToys.AwakeModuleInterface.dll",
|
||||
"PowerToys.Awake.exe",
|
||||
"PowerToys.Awake.dll",
|
||||
|
||||
"PowerToys.FancyZonesEditor.exe",
|
||||
"PowerToys.FancyZonesEditor.dll",
|
||||
"PowerToys.FancyZonesEditorCommon.dll",
|
||||
"PowerToys.FancyZonesModuleInterface.dll",
|
||||
"PowerToys.FancyZones.exe",
|
||||
"FancyZonesCLI.exe",
|
||||
"FancyZonesCLI.dll",
|
||||
|
||||
"PowerToys.GcodePreviewHandler.dll",
|
||||
"PowerToys.GcodePreviewHandler.exe",
|
||||
"PowerToys.GcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.exe",
|
||||
"PowerToys.GcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.BgcodePreviewHandler.dll",
|
||||
"PowerToys.BgcodePreviewHandler.exe",
|
||||
"PowerToys.BgcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.BgcodeThumbnailProvider.dll",
|
||||
"PowerToys.BgcodeThumbnailProvider.exe",
|
||||
"PowerToys.BgcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.exe",
|
||||
"PowerToys.MarkdownPreviewHandlerCpp.dll",
|
||||
"PowerToys.MonacoPreviewHandler.dll",
|
||||
"PowerToys.MonacoPreviewHandler.exe",
|
||||
"PowerToys.MonacoPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfPreviewHandler.dll",
|
||||
"PowerToys.PdfPreviewHandler.exe",
|
||||
"PowerToys.PdfPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfThumbnailProvider.dll",
|
||||
"PowerToys.PdfThumbnailProvider.exe",
|
||||
"PowerToys.PdfThumbnailProviderCpp.dll",
|
||||
"PowerToys.powerpreview.dll",
|
||||
"PowerToys.PreviewHandlerCommon.dll",
|
||||
"PowerToys.QoiPreviewHandler.dll",
|
||||
"PowerToys.QoiPreviewHandler.exe",
|
||||
"PowerToys.QoiPreviewHandlerCpp.dll",
|
||||
"PowerToys.QoiThumbnailProvider.dll",
|
||||
"PowerToys.QoiThumbnailProvider.exe",
|
||||
"PowerToys.QoiThumbnailProviderCpp.dll",
|
||||
"PowerToys.StlThumbnailProvider.dll",
|
||||
"PowerToys.StlThumbnailProvider.exe",
|
||||
"PowerToys.StlThumbnailProviderCpp.dll",
|
||||
"PowerToys.SvgPreviewHandler.dll",
|
||||
"PowerToys.SvgPreviewHandler.exe",
|
||||
"PowerToys.SvgPreviewHandlerCpp.dll",
|
||||
"PowerToys.SvgThumbnailProvider.dll",
|
||||
"PowerToys.SvgThumbnailProvider.exe",
|
||||
"PowerToys.SvgThumbnailProviderCpp.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.exe",
|
||||
@@ -129,7 +106,6 @@
|
||||
"WinUI3Apps\\PowerToys.QuickAccess.exe",
|
||||
"WinUI3Apps\\PowerToys.Settings.UI.Controls.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.exe",
|
||||
@@ -142,7 +118,6 @@
|
||||
"PowerToys.ImageResizerContextMenu.dll",
|
||||
"ImageResizerContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.LightSwitchModuleInterface.dll",
|
||||
"LightSwitchService\\PowerToys.LightSwitchService.exe",
|
||||
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
@@ -178,7 +153,6 @@
|
||||
"RunPlugins\\WebSearch\\Community.PowerToys.Run.Plugin.WebSearch.dll",
|
||||
"RunPlugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.MeasureToolModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolCore.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.exe",
|
||||
@@ -194,7 +168,6 @@
|
||||
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
"PowerToys.MouseWithoutBordersService.dll",
|
||||
"PowerToys.MouseWithoutBordersService.exe",
|
||||
"PowerToys.MouseWithoutBordersHelper.dll",
|
||||
@@ -207,7 +180,6 @@
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
|
||||
"PowerToys.PowerDisplayModuleInterface.dll",
|
||||
@@ -227,7 +199,6 @@
|
||||
"PowerToys.WorkspacesEditor.dll",
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
@@ -236,16 +207,13 @@
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"PowerToys.ModuleContracts.dll",
|
||||
"Awake.ModuleServices.dll",
|
||||
|
||||
@@ -8,6 +8,17 @@
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Generate version data -->
|
||||
<Target Name="GenerateVersionData" BeforeTargets="PrepareForBuild">
|
||||
<ItemGroup>
|
||||
<HeaderLines Include="#pragma once" />
|
||||
<HeaderLines Include="#define VERSION_MAJOR $(Version.Split('.')[0])" />
|
||||
<HeaderLines Include="#define VERSION_MINOR $(Version.Split('.')[1])" />
|
||||
<HeaderLines Include="#define VERSION_REVISION $(Version.Split('.')[2])" />
|
||||
</ItemGroup>
|
||||
<WriteLinesToFile File="Generated Files\version_gen.h" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
||||
</Target>
|
||||
|
||||
<!-- Project configurations -->
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
|
||||
318
PowerToys.slnx
318
PowerToys.slnx
@@ -17,7 +17,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/COMUtils/COMUtils.vcxproj" Id="7319089e-46d6-4400-bc65-e39bdf1416ee" />
|
||||
<Project Path="src/common/Display/Display.vcxproj" Id="caba8dfb-823b-4bf2-93ac-3f31984150d9" />
|
||||
<Project Path="src/common/FilePreviewCommon/FilePreviewCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
@@ -56,8 +55,6 @@
|
||||
</Project>
|
||||
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
||||
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
||||
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
|
||||
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
</Folder>
|
||||
<Folder Name="/common/interop/">
|
||||
<Project Path="src/common/interop/interop-tests/Common.Interop.UnitTests.csproj">
|
||||
@@ -117,8 +114,10 @@
|
||||
<File Path="src/common/utils/string_utils.h" />
|
||||
<File Path="src/common/utils/timeutil.h" />
|
||||
<File Path="src/common/utils/UnhandledExceptionHandler.h" />
|
||||
<File Path="src/common/utils/version.h" />
|
||||
<File Path="src/common/utils/winapi_error.h" />
|
||||
<File Path="src/common/utils/window.h" />
|
||||
<File Path="version.h" />
|
||||
</Folder>
|
||||
<Folder Name="/DSC/">
|
||||
<Project Path="src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj">
|
||||
@@ -144,7 +143,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
<Deploy />
|
||||
</Project>
|
||||
<Project Path="src/modules/AdvancedPaste/AdvancedPasteModuleInterface/AdvancedPasteModuleInterface.vcxproj" Id="fc373b24-3293-453c-aaf5-cf2909dcee6a" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/AdvancedPaste/Tests/">
|
||||
<Project Path="src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj">
|
||||
@@ -158,7 +156,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/AlwaysOnTop/">
|
||||
<Project Path="src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj" Id="1dc3be92-ce89-43fb-8110-9c043a2fe7a2" />
|
||||
<Project Path="src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj" Id="48a0a19e-a0be-4256-acf8-cc3b80291af9" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/awake/">
|
||||
<Project Path="src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj">
|
||||
@@ -169,19 +166,12 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" Id="5e7360a8-d048-4ed3-8f09-0bfd64c5529a" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/cmdNotFound/">
|
||||
<Project Path="src/modules/cmdNotFound/CmdNotFoundModuleInterface/CmdNotFoundModuleInterface.vcxproj" Id="0014d652-901f-4456-8d65-06fc5f997fb0" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/colorpicker/">
|
||||
<Project Path="src/modules/colorPicker/ColorPicker.ModuleServices/ColorPicker.ModuleServices.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" Id="655c9af2-18d3-4da6-80e4-85504a7722ba">
|
||||
<BuildDependency Project="src/common/logger/logger.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -195,7 +185,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/CommandPalette/">
|
||||
<Project Path="src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj" Id="5f63c743-f6ce-4dba-a200-2b3f8a14e8c2" />
|
||||
<Project Path="src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj" Id="0adeb797-c8c7-4ffa-acd5-2af6cad7ecd8" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/CommandPalette/Built-in Extensions/">
|
||||
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj">
|
||||
@@ -380,14 +369,12 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/CropAndLock/">
|
||||
<Project Path="src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj" Id="f5e1146e-b7b3-4e11-85fd-270a500bd78c" />
|
||||
<Project Path="src/modules/CropAndLock/CropAndLockModuleInterface/CropAndLockModuleInterface.vcxproj" Id="3157fa75-86cf-4ee2-8f62-c43f776493c6" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/EnvironmentVariables/">
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/EnvironmentVariablesModuleInterface.vcxproj" Id="b9420661-b0e4-4241-abd4-4a27a1f64250" />
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesUILib/EnvironmentVariablesUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/fancyzones/">
|
||||
@@ -405,7 +392,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" Id="f9c68edf-ac74-4b77-9af1-005d9c9f6a99" />
|
||||
<Project Path="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" Id="48804216-2a0e-4168-a6d8-9cd068d14227" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/fancyzones/Tests/">
|
||||
<Project Path="src/modules/fancyzones/FancyZones.FuzzTests/FancyZones.FuzzTests.csproj">
|
||||
@@ -428,8 +414,121 @@
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/File Explorer/">
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandler/BgcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProvider/BgcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/Common/PreviewHandlerCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/FileExplorerDllExporter/FileExplorerDllExporter.vcxproj" Id="f6088a11-1c9e-4420-aa90-cf7e78dd7f1c" />
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandler/GcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProvider/GcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandler/QoiPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProvider/QoiThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/File Explorer/Tests/">
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodePreviewHandler/Preview.BgcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodeThumbnailProvider/Preview.BgcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodePreviewHandler/Preview.GcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodeThumbnailProvider/Preview.GcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-MarkdownPreviewHandler/Preview.MarkdownPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfPreviewHandler/Preview.PdfPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfThumbnailProvider/Preview.PdfThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PreviewHandlerCommon/Preview.PreviewHandlerCommon.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiPreviewHandler/Preview.QoiPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiThumbnailProvider/Preview.QoiThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-StlThumbnailProvider/Preview.StlThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgPreviewHandler/Preview.SvgPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgThumbnailProvider/Preview.SvgThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49D456D3-F485-45AF-8875-45B44F193DDC" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49d456d3-f485-45af-8875-45b44f193ddc" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
||||
@@ -440,14 +539,13 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/Tests/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="A1B2C3D4-E5F6-7890-1234-567890ABCDEF" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-1234-567890abcdef" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Hosts/">
|
||||
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj" Id="b41b888c-7db8-4747-b262-4062e05a230d" />
|
||||
<Project Path="src/modules/Hosts/HostsUILib/HostsUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Hosts/Tests/">
|
||||
@@ -466,13 +564,13 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/imageresizer/">
|
||||
<Project Path="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" Id="0b43679e-edfa-4da0-ad30-f4628b308b1b" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
||||
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
||||
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
||||
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
@@ -483,12 +581,8 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/interface/">
|
||||
<File Path="src/modules/interface/powertoy_module_interface.h" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/keyboardmanager/">
|
||||
<Project Path="src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj" Id="8affa899-0b73-49ec-8c50-0fadda57b2fc" />
|
||||
<Project Path="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" Id="89f34af7-1c34-4a72-aa6e-534bcf972bd9" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj" Id="8df78b53-200e-451f-9328-01eb907193ae" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorLibrary.vcxproj" Id="23d2070d-e4ad-4add-85a7-083d9c76ad49" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.vcxproj" Id="4382a954-179a-4078-92af-715187dfff50" />
|
||||
@@ -504,9 +598,6 @@
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngineTest/KeyboardManagerEngineTest.vcxproj" Id="7f4b3a60-bc27-45a7-8000-68b0b6ea7466" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/launcher/">
|
||||
<Project Path="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" Id="e364f67b-bb12-4e91-b639-355866ebcd8b">
|
||||
<BuildDependency Project="src/modules/launcher/PowerLauncher/PowerLauncher.csproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/launcher/PowerLauncher.Telemetry/PowerLauncher.Telemetry.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -674,8 +765,6 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/LightSwitch/">
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj" Id="79267138-2895-4346-9021-21408d65379f" />
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" Id="38177d56-6ad1-4adf-88c9-2843a7932166" />
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" Id="08e71c67-6a7e-4ca1-b04e-2fb336410bac" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/LightSwitch/Tests/">
|
||||
@@ -694,7 +783,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj" Id="d1234567-8901-2345-6789-abcdef012345" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/Tests/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
|
||||
@@ -706,9 +794,7 @@
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj" Id="54a93af7-60c7-4f6c-99d2-fbb1f75f853a">
|
||||
<BuildDependency Project="src/common/Display/Display.vcxproj" />
|
||||
<BuildDependency Project="src/common/SettingsAPI/SettingsAPI.vcxproj" />
|
||||
<BuildDependency Project="src/common/version/version.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolModuleInterface/MeasureToolModuleInterface.vcxproj" Id="92c39820-9f84-4529-bc7d-22aae514d63b" />
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -728,7 +814,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MouseJump/MouseJump.vcxproj" Id="8a08d663-4995-40e3-b42c-3f910625f284" />
|
||||
<Project Path="src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -758,7 +843,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseWithoutBorders/ModuleInterface/MouseWithoutBordersModuleInterface.vcxproj" Id="2833c9c6-ab32-4048-a5c7-a70898337b57" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseWithoutBorders/Tests/">
|
||||
<Project Path="src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj">
|
||||
@@ -800,14 +884,12 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/poweraccent/PowerAccentKeyboardService/PowerAccentKeyboardService.vcxproj" Id="c97d9a5d-206c-454e-997e-009e227d7f02" />
|
||||
<Project Path="src/modules/poweraccent/PowerAccentModuleInterface/PowerAccentModuleInterface.vcxproj" Id="34a354c5-23c7-4343-916c-c52daf4fc39d" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerOCR/">
|
||||
<Project Path="src/modules/PowerOCR/PowerOCR/PowerOCR.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/PowerOCR/PowerOCRModuleInterface/PowerOCRModuleInterface.vcxproj" Id="6ab6a2d6-f859-4a82-9184-0bd29c9f07d1" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerOCR/Tests/">
|
||||
<Project Path="src/modules/PowerOCR/PowerOCR-UITests/PowerOCR.UITests.csproj">
|
||||
@@ -837,140 +919,11 @@
|
||||
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/previewpane/">
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandler/BgcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandlerCpp/BgcodePreviewHandlerCpp.vcxproj" Id="f6088a11-1c9e-4420-aa90-cf7e78dd7f1c" />
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProvider/BgcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProviderCpp/BgcodeThumbnailProviderCpp.vcxproj" Id="47b0678c-806b-4fe1-9f50-46ba88989532" />
|
||||
<Project Path="src/modules/previewpane/Common/PreviewHandlerCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandler/GcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandlerCpp.vcxproj" Id="5a5dd09d-723a-44d3-8f2b-293584c3d731" />
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProvider/GcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProviderCpp/GcodeThumbnailProviderCpp.vcxproj" Id="56cc2f10-6e41-453d-be16-c593a5e58482" />
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandlerCpp.vcxproj" Id="ed9a1ac6-aeb0-4569-a6e9-e1696182b545" />
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandlerCpp.vcxproj" Id="b3e869c4-8210-4ebd-a621-ff4c4afcbfa9" />
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandlerCpp.vcxproj" Id="54f7c616-fd41-4e62-bff9-015686914f4d" />
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProviderCpp/PdfThumbnailProviderCpp.vcxproj" Id="ca5518ed-0458-4b09-8f53-4122b9888655" />
|
||||
<Project Path="src/modules/previewpane/powerpreview/powerpreview.vcxproj" Id="217df501-135c-4e38-bfc8-99d4821032ea">
|
||||
<BuildDependency Project="src/common/version/version.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandler/QoiPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandlerCpp.vcxproj" Id="3baf9c81-a194-4925-a035-5e24a5d1e542" />
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProvider/QoiThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProviderCpp/QoiThumbnailProviderCpp.vcxproj" Id="ccb5e44f-84d9-4203-83c6-1c9ec9302bc7" />
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProviderCpp/StlThumbnailProviderCpp.vcxproj" Id="d6dcc3ae-18c0-488a-b978-baa9e3cff09d" />
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandlerCpp.vcxproj" Id="143f13e3-d2e3-4d83-b035-356612d99956" />
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProviderCpp/SvgThumbnailProviderCpp.vcxproj" Id="2bbc9e33-21ec-401c-84da-bb6590a9b2aa" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/previewpane/Tests/">
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodePreviewHandler/Preview.BgcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodeThumbnailProvider/Preview.BgcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodePreviewHandler/Preview.GcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodeThumbnailProvider/Preview.GcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-MarkdownPreviewHandler/Preview.MarkdownPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfPreviewHandler/Preview.PdfPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfThumbnailProvider/Preview.PdfThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PreviewHandlerCommon/Preview.PreviewHandlerCommon.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiPreviewHandler/Preview.QoiPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiThumbnailProvider/Preview.QoiThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-StlThumbnailProvider/Preview.StlThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgPreviewHandler/Preview.SvgPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgThumbnailProvider/Preview.SvgThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/RegistryPreview/">
|
||||
<Project Path="src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/registrypreview/RegistryPreviewExt/RegistryPreviewExt.vcxproj" Id="697c6af9-0a48-49a9-866c-67da12384015" />
|
||||
<Project Path="src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/RegistryPreview/Test/">
|
||||
@@ -981,7 +934,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/shortcutguide/">
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj" Id="2edb3eb4-fa92-4bff-b2d8-566584837231" />
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="2d604c07-51fc-46bb-9eb7-75aecc7f5e81" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Workspaces/">
|
||||
<Project Path="src/modules/Workspaces/Workspaces.ModuleServices/Workspaces.ModuleServices.csproj">
|
||||
@@ -1002,7 +954,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/Workspaces/WorkspacesLib/WorkspacesLib.vcxproj" Id="b31fcc55-b5a4-4ea7-b414-2dceae6af332" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesModuleInterface/WorkspacesModuleInterface.vcxproj" Id="45285df2-9742-4eca-9ac9-58951fc26489" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesSnapshotTool/WorkspacesSnapshotTool.vcxproj" Id="3d63307b-9d27-44fd-b033-b26f39245b85" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesWindowArranger/WorkspacesWindowArranger.vcxproj" Id="37d07516-4185-43a4-924f-3c7a5d95ecf6" />
|
||||
</Folder>
|
||||
@@ -1028,7 +979,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/ZoomIt/">
|
||||
<Project Path="src/modules/ZoomIt/ZoomIt/ZoomIt.vcxproj" Id="0a84f764-3a88-44cd-aa96-41bdbd48627b" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItModuleInterface/ZoomItModuleInterface.vcxproj" Id="e4585179-2ac1-4d5f-a3ff-cfc5392f694c" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
|
||||
</Folder>
|
||||
<Folder Name="/settings-ui/">
|
||||
@@ -1073,37 +1023,35 @@
|
||||
<File Path="src/Solution.props" />
|
||||
<File Path="src/Version.props" />
|
||||
</Folder>
|
||||
<Project Path="src/ActionRunner/ActionRunner.vcxproj" Id="d29ddd63-e2cf-4657-9fd5-2aede4257e5d">
|
||||
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/PackageIdentity/PackageIdentity.vcxproj" Id="e2a5a82e-1e5b-4c8d-9a4f-2b1a8f9e5c3d" />
|
||||
<Project Path="src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/runner/runner.vcxproj" Id="9412d5c6-2cf2-4fc2-a601-b55508ea9b27">
|
||||
<BuildDependency Project="src/ActionRunner/ActionRunner.vcxproj" />
|
||||
<BuildDependency Project="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" />
|
||||
<BuildDependency Project="src/common/notifications/BackgroundActivatorDLL/BackgroundActivatorDLL.vcxproj" />
|
||||
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
||||
<BuildDependency Project="src/modules/awake/Awake/Awake.csproj" />
|
||||
<BuildDependency Project="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" />
|
||||
<BuildDependency Project="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" />
|
||||
<BuildDependency Project="src/modules/imageresizer/ui/ImageResizerUI.csproj" />
|
||||
<BuildDependency Project="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" />
|
||||
<BuildDependency Project="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" />
|
||||
<BuildDependency Project="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" />
|
||||
<BuildDependency Project="src/modules/powerrename/dll/PowerRenameExt.vcxproj" />
|
||||
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/Common/PreviewHandlerCommon.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/powerpreview/powerpreview.vcxproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/PackageIdentity/PackageIdentity.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
|
||||
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
|
||||
<Project Path="src/RunnerV2/RunnerV2/RunnerV2.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/Update/Update.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Solution>
|
||||
|
||||
@@ -68,7 +68,6 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an
|
||||
- Add the `In progress` label to the issue, if not already present. Also add a `Cost-Small/Medium/Large` estimate and make sure all appropriate labels are set.
|
||||
- If you are a community contributor, you will not be able to add labels to the issue; in that case just add a comment saying that you have started work on the issue and try to give an estimate for the delivery date.
|
||||
- If the work item has a medium/large cost, using the markdown task list, list each sub item and update the list with a check mark after completing each sub item.
|
||||
- **Before opening a PR, ensure your changes build successfully locally and functionality tests pass.** This is especially important for AI-assisted (vibe coding) contributions—always verify AI-generated code works as intended. Exploratory PRs or draft PRs for discussion are exceptions.
|
||||
- When opening a PR, follow the PR template.
|
||||
- When you'd like the team to take a look (even if the work is not yet fully complete) mark the PR as 'Ready For Review' so that the team can review your work and provide comments, suggestions, and request changes. It may take several cycles, but the end result will be solid, testable, conformant code that is safe for us to merge.
|
||||
- When the PR is approved, let the owner of the PR merge it. For community contributions, the reviewer who approved the PR can also merge it.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
#include "../../src/common/utils/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
<Custom Action="UnRegisterCmdPalPackage" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UninstallCommandNotFound" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UpgradeCommandNotFound" After="InstallFiles" Condition="WIX_UPGRADE_DETECTED" />
|
||||
<Custom Action="UninstallPackageIdentityMSIX" Before="RemoveFiles" Condition="Installed AND (REMOVE="ALL")" />
|
||||
<Custom Action="UninstallPackageIdentityMSIX" Before="RemoveFiles" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<Custom Action="UninstallServicesTask" After="InstallFinalize" Condition="Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE" xml:space="preserve">
|
||||
<value>Couldn't download .NET Core Desktop Runtime 3.1, please install it manually.</value>
|
||||
</data>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
|
||||
<value>PowerToys installation error</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
|
||||
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,36 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../common/version/version.h"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
@@ -1,109 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include "../runner/tray_icon.h"
|
||||
#include "../runner/ActionRunnerUtils.h"
|
||||
|
||||
using namespace cmdArg;
|
||||
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
int nArgs = 0;
|
||||
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
||||
if (!args || nArgs < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring_view action{ args[1] };
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
|
||||
logFilePath.append(LogSettings::actionRunnerLogPath);
|
||||
Logger::init(LogSettings::actionRunnerLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
|
||||
if (action == RUN_NONELEVATED)
|
||||
{
|
||||
int nextArg = 2;
|
||||
|
||||
std::wstring_view target;
|
||||
std::wstring_view pidFile;
|
||||
std::wstring params;
|
||||
|
||||
while (nextArg < nArgs)
|
||||
{
|
||||
if (std::wstring_view(args[nextArg]) == L"-target" && nextArg + 1 < nArgs)
|
||||
{
|
||||
target = args[nextArg + 1];
|
||||
nextArg += 2;
|
||||
}
|
||||
else if (std::wstring_view(args[nextArg]) == L"-pidFile" && nextArg + 1 < nArgs)
|
||||
{
|
||||
pidFile = args[nextArg + 1];
|
||||
nextArg += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
params += args[nextArg];
|
||||
params += L' ';
|
||||
nextArg++;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE hMapFile = NULL;
|
||||
PDWORD pidBuffer = NULL;
|
||||
|
||||
if (!pidFile.empty())
|
||||
{
|
||||
hMapFile = OpenFileMappingW(FILE_MAP_WRITE, FALSE, pidFile.data());
|
||||
if (hMapFile)
|
||||
{
|
||||
pidBuffer = static_cast<PDWORD>(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(DWORD)));
|
||||
if (pidBuffer)
|
||||
{
|
||||
*pidBuffer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_same_elevation(target.data(), params, pidBuffer);
|
||||
|
||||
if (!pidFile.empty())
|
||||
{
|
||||
if (pidBuffer)
|
||||
{
|
||||
FlushViewOfFile(pidBuffer, sizeof(DWORD));
|
||||
UnmapViewOfFile(pidBuffer);
|
||||
}
|
||||
|
||||
if (hMapFile)
|
||||
{
|
||||
FlushFileBuffers(hMapFile);
|
||||
CloseHandle(hMapFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h actionRunner.base.rc actionRunner.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}</ProjectGuid>
|
||||
<RootNamespace>actionRunner</RootNamespace>
|
||||
<ProjectName>PowerToys.ActionRunner</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\deps\expected.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup>
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WindowsApp.lib;Msi.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ActionRunner.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ActionRunner.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\ActionRunner.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by PowerToys.ActionRunner.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys ActionRunner"
|
||||
#define INTERNAL_NAME "PowerToys.ActionRunner"
|
||||
#define ORIGINAL_FILENAME "PowerToys.ActionRunner.exe"
|
||||
|
||||
11
src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj
Normal file
11
src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj
Normal file
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
119
src/PowerToys.ActionRunner/Program.cs
Normal file
119
src/PowerToys.ActionRunner/Program.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PowerToys.ActionRunner;
|
||||
|
||||
internal sealed partial class Program
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0])
|
||||
{
|
||||
case "-run-non-elevated":
|
||||
ExecuteRunNonElevated(args[1..]);
|
||||
break;
|
||||
default:
|
||||
Environment.Exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteRunNonElevated(string[] args)
|
||||
{
|
||||
string? target = null;
|
||||
string? pidFile = null;
|
||||
string? arguments = null;
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
string arg = args[i];
|
||||
if (arg == "-target" && i + 1 < args.Length)
|
||||
{
|
||||
target = args[i + 1];
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (arg == "-pidFile" && i + 1 < args.Length)
|
||||
{
|
||||
pidFile = args[i + 1];
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
arguments = args[i + 1] + " ";
|
||||
i++;
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(pidFile))
|
||||
{
|
||||
IntPtr pidBuffer = IntPtr.Zero;
|
||||
IntPtr mapFile = OpenFileMapping(0x0002 /* FILE_MAP_WRITE */, false, pidFile);
|
||||
if (mapFile != IntPtr.Zero)
|
||||
{
|
||||
pidBuffer = MapViewOfFile(mapFile, 0x001F /* FILE_MAP_ALL_ACCESS */, 0, 0, sizeof(uint));
|
||||
if (pidBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt32(pidBuffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Process? p = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = target,
|
||||
Arguments = arguments.Trim(),
|
||||
UseShellExecute = true,
|
||||
});
|
||||
|
||||
if (pidBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt32(pidBuffer, p?.Id ?? 0);
|
||||
FlushViewOfFile(pidBuffer, sizeof(uint));
|
||||
UnmapViewOfFile(pidBuffer);
|
||||
}
|
||||
|
||||
if (mapFile != IntPtr.Zero)
|
||||
{
|
||||
FlushFileBuffers(mapFile);
|
||||
CloseHandle(mapFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
private static partial IntPtr OpenFileMapping(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool UnmapViewOfFile(IntPtr lpBaseAddress);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool FlushViewOfFile(IntPtr lpBaseAddress, uint dwNumberOfBytesToFlush);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool FlushFileBuffers(IntPtr hFile);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool CloseHandle(IntPtr hObject);
|
||||
}
|
||||
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysDark.ico
Normal file
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysDark.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysLight.ico
Normal file
BIN
src/RunnerV2/RunnerV2/Assets/PowerToysLight.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
17
src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs
Normal file
17
src/RunnerV2/RunnerV2/Extensions/PackageVersionExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace RunnerV2.Extensions
|
||||
{
|
||||
internal static class PackageVersionExtensions
|
||||
{
|
||||
public static Version ToVersion(this PackageVersion packageVersion)
|
||||
{
|
||||
return new Version(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/RunnerV2/RunnerV2/Helpers/COMUtils.cs
Normal file
57
src/RunnerV2/RunnerV2/Helpers/COMUtils.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class COMUtils
|
||||
{
|
||||
public static void InitializeCOMSecurity(string securityDescriptor)
|
||||
{
|
||||
if (!NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||
securityDescriptor,
|
||||
1,
|
||||
out IntPtr pSD,
|
||||
out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint absoluteSDSize = 0;
|
||||
uint daclSize = 0;
|
||||
uint groupSize = 0;
|
||||
uint ownerSize = 0;
|
||||
uint saclSize = 0;
|
||||
|
||||
if (!NativeMethods.MakeAbsoluteSD(pSD, IntPtr.Zero, ref absoluteSDSize, IntPtr.Zero, ref daclSize, IntPtr.Zero, ref saclSize, IntPtr.Zero, ref ownerSize, IntPtr.Zero, ref groupSize))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr absoluteSD = Marshal.AllocHGlobal((int)absoluteSDSize);
|
||||
IntPtr dacl = Marshal.AllocHGlobal((int)daclSize);
|
||||
IntPtr sacl = Marshal.AllocHGlobal((int)saclSize);
|
||||
IntPtr owner = Marshal.AllocHGlobal((int)ownerSize);
|
||||
IntPtr group = Marshal.AllocHGlobal((int)groupSize);
|
||||
|
||||
if (!NativeMethods.MakeAbsoluteSD(pSD, absoluteSD, ref absoluteSDSize, dacl, ref daclSize, sacl, ref saclSize, owner, ref ownerSize, group, ref groupSize))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_ = NativeMethods.CoInitializeSecurity(
|
||||
absoluteSD,
|
||||
-1,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
6, // RPC_C_AUTHN_LEVEL_PKT_PRIVACY
|
||||
2, // RPC_C_IMP_LEVEL_IDENTIFY
|
||||
IntPtr.Zero,
|
||||
64 | 4096, // EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
218
src/RunnerV2/RunnerV2/Helpers/CentralizedKeyboardHookManager.cs
Normal file
218
src/RunnerV2/RunnerV2/Helpers/CentralizedKeyboardHookManager.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Windows.System;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class CentralizedKeyboardHookManager
|
||||
{
|
||||
private static readonly UIntPtr _ignoreKeyEventFlag = 0x5555;
|
||||
|
||||
private static readonly Dictionary<string, List<(HotkeySettings HotkeySettings, Action Action)>> _keyboardHooks = [];
|
||||
|
||||
private static HotkeySettingsControlHook _hotkeySettingsControlHook = new(OnKeyDown, OnKeyUp, IsActive, (_, specialFlags) => specialFlags != _ignoreKeyEventFlag);
|
||||
|
||||
private static void OnKeyDown(int key)
|
||||
{
|
||||
if ((VirtualKey)key == VirtualKey.RightMenu && _ctrlState)
|
||||
{
|
||||
_ctrlAltState = true;
|
||||
}
|
||||
|
||||
switch ((VirtualKey)key)
|
||||
{
|
||||
case VirtualKey.Control:
|
||||
case VirtualKey.LeftControl:
|
||||
case VirtualKey.RightControl:
|
||||
_ctrlState = true;
|
||||
break;
|
||||
case VirtualKey.Menu:
|
||||
case VirtualKey.LeftMenu:
|
||||
case VirtualKey.RightMenu:
|
||||
_altState = true;
|
||||
break;
|
||||
case VirtualKey.Shift:
|
||||
case VirtualKey.LeftShift:
|
||||
case VirtualKey.RightShift:
|
||||
_shiftState = true;
|
||||
break;
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_winState = true;
|
||||
break;
|
||||
default:
|
||||
if (OnKeyboardEvent(new HotkeySettings
|
||||
{
|
||||
Code = key,
|
||||
Ctrl = _ctrlState,
|
||||
Alt = _altState,
|
||||
Shift = _shiftState,
|
||||
Win = _winState,
|
||||
}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyDown);
|
||||
}
|
||||
|
||||
private static void OnKeyUp(int key)
|
||||
{
|
||||
switch ((VirtualKey)key)
|
||||
{
|
||||
case VirtualKey.Control:
|
||||
case VirtualKey.LeftControl:
|
||||
case VirtualKey.RightControl:
|
||||
_ctrlState = false;
|
||||
break;
|
||||
case VirtualKey.Menu:
|
||||
case VirtualKey.LeftMenu:
|
||||
case VirtualKey.RightMenu:
|
||||
_altState = false;
|
||||
break;
|
||||
case VirtualKey.Shift:
|
||||
case VirtualKey.LeftShift:
|
||||
case VirtualKey.RightShift:
|
||||
_shiftState = false;
|
||||
break;
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_winState = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Correctly release Ctrl key if Ctrl+Alt (AltGr) was used.
|
||||
if (_ctrlAltState && (VirtualKey)key == VirtualKey.RightMenu)
|
||||
{
|
||||
_ctrlAltState = false;
|
||||
_ctrlState = false;
|
||||
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftControl, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||
}
|
||||
|
||||
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||
}
|
||||
|
||||
private static bool _ctrlState;
|
||||
private static bool _altState;
|
||||
private static bool _shiftState;
|
||||
private static bool _winState;
|
||||
private static bool _ctrlAltState;
|
||||
|
||||
private static bool _isActive;
|
||||
|
||||
private static bool IsActive()
|
||||
{
|
||||
return _isActive;
|
||||
}
|
||||
|
||||
public static void AddKeyboardHook(string moduleName, HotkeySettings hotkeySettings, Action action)
|
||||
{
|
||||
#pragma warning disable CA1854 // Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method
|
||||
if (!_keyboardHooks.ContainsKey(moduleName))
|
||||
{
|
||||
_keyboardHooks[moduleName] = [];
|
||||
}
|
||||
#pragma warning restore CA1854 // Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method
|
||||
|
||||
_keyboardHooks[moduleName].Add((hotkeySettings, action));
|
||||
}
|
||||
|
||||
public static void RemoveAllHooksFromModule(string moduleName)
|
||||
{
|
||||
_keyboardHooks.Remove(moduleName);
|
||||
}
|
||||
|
||||
private static bool OnKeyboardEvent(HotkeySettings pressedHotkey)
|
||||
{
|
||||
bool shortcutHandled = false;
|
||||
|
||||
foreach (var moduleHooks in _keyboardHooks.Values)
|
||||
{
|
||||
foreach (var (hotkeySettings, action) in moduleHooks)
|
||||
{
|
||||
if (hotkeySettings == pressedHotkey)
|
||||
{
|
||||
action();
|
||||
shortcutHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shortcutHandled;
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (_hotkeySettingsControlHook.GetDisposedState())
|
||||
{
|
||||
_hotkeySettingsControlHook = new(OnKeyDown, OnKeyUp, IsActive, (_, specialFlags) => specialFlags != _ignoreKeyEventFlag);
|
||||
}
|
||||
|
||||
_isActive = true;
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
_isActive = false;
|
||||
_hotkeySettingsControlHook.Dispose();
|
||||
}
|
||||
|
||||
// Function to send a single key event to the system which would be ignored by the hotkey control.
|
||||
private static void SendSingleKeyboardInput(short keyCode, uint keyStatus)
|
||||
{
|
||||
if (IsExtendedVirtualKey(keyCode))
|
||||
{
|
||||
keyStatus |= (uint)NativeKeyboardHelper.KeyEventF.ExtendedKey;
|
||||
}
|
||||
|
||||
NativeKeyboardHelper.INPUT input = new()
|
||||
{
|
||||
type = NativeKeyboardHelper.INPUTTYPE.INPUT_KEYBOARD,
|
||||
data = new NativeKeyboardHelper.InputUnion
|
||||
{
|
||||
ki = new NativeKeyboardHelper.KEYBDINPUT
|
||||
{
|
||||
wVk = keyCode,
|
||||
dwFlags = keyStatus,
|
||||
dwExtraInfo = _ignoreKeyEventFlag,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
NativeKeyboardHelper.INPUT[] inputs = [input];
|
||||
|
||||
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
|
||||
}
|
||||
|
||||
private static bool IsExtendedVirtualKey(short vk)
|
||||
{
|
||||
return vk switch
|
||||
{
|
||||
0xA5 => true, // VK_RMENU (Right Alt - AltGr)
|
||||
0xA3 => true, // VK_RCONTROL
|
||||
0x2D => true, // VK_INSERT
|
||||
0x2E => true, // VK_DELETE
|
||||
0x23 => true, // VK_END
|
||||
0x24 => true, // VK_HOME
|
||||
0x21 => true, // VK_PRIOR (Page Up)
|
||||
0x22 => true, // VK_NEXT (Page Down)
|
||||
0x25 => true, // VK_LEFT
|
||||
0x26 => true, // VK_UP
|
||||
0x27 => true, // VK_RIGHT
|
||||
0x28 => true, // VK_DOWN
|
||||
0x90 => true, // VK_NUMLOCK
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs
Normal file
93
src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static partial class ElevationHelper
|
||||
{
|
||||
internal static RestartScheduledMode RestartScheduled { get; set; } = RestartScheduledMode.None;
|
||||
|
||||
internal enum RestartScheduledMode
|
||||
{
|
||||
None,
|
||||
RestartElevated,
|
||||
RestartElevatedWithOpenSettings,
|
||||
RestartNonElevated,
|
||||
}
|
||||
|
||||
private static bool? _cachedValue;
|
||||
|
||||
internal static void RestartIfScheudled()
|
||||
{
|
||||
switch (RestartScheduled)
|
||||
{
|
||||
case RestartScheduledMode.None:
|
||||
return;
|
||||
case RestartScheduledMode.RestartElevated:
|
||||
RestartAsAdministrator("--restartedElevated");
|
||||
break;
|
||||
case RestartScheduledMode.RestartElevatedWithOpenSettings:
|
||||
RestartAsAdministrator("--restartedElevated --open-settings");
|
||||
break;
|
||||
case RestartScheduledMode.RestartNonElevated:
|
||||
// Todo: restart unelevated
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RestartAsAdministrator(string arguments)
|
||||
{
|
||||
Logger.LogInfo("Restarting as administrator, because it was scheudled.");
|
||||
|
||||
ProcessStartInfo processStartInfo = new()
|
||||
{
|
||||
Arguments = arguments,
|
||||
Verb = "runas",
|
||||
UseShellExecute = true,
|
||||
FileName = Environment.ProcessPath,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(processStartInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to restart as administrator.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsProcessElevated(bool useCachedValue = true)
|
||||
{
|
||||
if (_cachedValue is not null && useCachedValue)
|
||||
{
|
||||
return _cachedValue.Value;
|
||||
}
|
||||
|
||||
bool elevated = false;
|
||||
if (OpenProcessToken(Process.GetCurrentProcess().Handle, TOKENQUERY, out nint token))
|
||||
{
|
||||
TokenElevation elevation = default;
|
||||
if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TOKEN_ELEVATION, ref elevation, (uint)Marshal.SizeOf(elevation), out uint _))
|
||||
{
|
||||
elevated = elevation.TokenIsElevated != 0;
|
||||
}
|
||||
|
||||
if (token != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(token);
|
||||
}
|
||||
}
|
||||
|
||||
_cachedValue = elevated;
|
||||
return elevated;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/RunnerV2/RunnerV2/Helpers/NotificationHelper.cs
Normal file
52
src/RunnerV2/RunnerV2/Helpers/NotificationHelper.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class NotificationHelper
|
||||
{
|
||||
public enum ToastType
|
||||
{
|
||||
ElevatedDontShowAgain,
|
||||
CouldntToggleFileExplorerModules,
|
||||
}
|
||||
|
||||
public static string GetToastKey(ToastType key) => key switch
|
||||
{
|
||||
ToastType.ElevatedDontShowAgain => @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain\{e16ea82f-6d94-4f30-bb02-d6d911588afd}",
|
||||
ToastType.CouldntToggleFileExplorerModules => @"(SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain\{7e29e2b2-b31c-4dcd-b7b0-79c078b02430})",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(key), key, null),
|
||||
};
|
||||
|
||||
public static bool DisableToast(ToastType type)
|
||||
{
|
||||
try
|
||||
{
|
||||
RegistryKey? key = Registry.CurrentUser.CreateSubKey(GetToastKey(type));
|
||||
|
||||
if (key != null)
|
||||
{
|
||||
key.SetValue(null, BitConverter.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeSeconds()), RegistryValueKind.QWord);
|
||||
key.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("Could not disable toast notification.", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
194
src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs
Normal file
194
src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Interop;
|
||||
using ManagedCommon;
|
||||
using RunnerV2.Extensions;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Foundation;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helper methods for working with UWP packages.
|
||||
/// </summary>
|
||||
internal static partial class PackageHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the registered UWP package based on the display name and version check.
|
||||
/// </summary>
|
||||
/// <param name="packageDisplayName">The display name of the package.</param>
|
||||
/// <param name="checkVersion">If true, the package version will be checked against the executing assembly version.</param>
|
||||
/// <returns>If a package is found the corresponding <see cref="Package"/> object. If none is found <c>null</c>.</returns>
|
||||
internal static Package? GetRegisteredPackage(string packageDisplayName, bool checkVersion)
|
||||
{
|
||||
PackageManager packageManager = new();
|
||||
foreach (var package in packageManager.FindPackagesForUser(null))
|
||||
{
|
||||
if (package.Id.FullName.Contains(packageDisplayName) && (!checkVersion || package.Id.Version.ToVersion() == Assembly.GetExecutingAssembly().GetName().Version))
|
||||
{
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static string[] FindMsixFiles(string directoryPath, bool recursive)
|
||||
{
|
||||
if (!Directory.Exists(directoryPath))
|
||||
{
|
||||
Logger.LogError("Tried to search msix files in " + directoryPath + ", but it does not exist.");
|
||||
return [];
|
||||
}
|
||||
|
||||
List<string> matchedFiles = [];
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(directoryPath, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
if (File.Exists(file) && msixPackagePattern().IsMatch(Path.GetFileName(file)))
|
||||
{
|
||||
matchedFiles.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("An error occured while searching for MSIX files.", e);
|
||||
}
|
||||
|
||||
return [.. matchedFiles];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs the specified appx package along with its dependencies.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package</param>
|
||||
/// <param name="dependencies">Array of dependency package paths</param>
|
||||
/// <returns>True if the installation was successful, false otherwise</returns>
|
||||
internal static bool InstallPackage(string packagePath, string[] dependencies, bool isSparsePackage = false)
|
||||
{
|
||||
Logger.LogInfo("Starting package install of package \"" + packagePath + "\"");
|
||||
PackageManager packageManager = new();
|
||||
List<Uri> uris = [];
|
||||
|
||||
if (IsPackageSatisfied(packagePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (string dependency in dependencies)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsPackageSatisfied(dependency))
|
||||
{
|
||||
Logger.LogInfo("Dependency \"" + dependency + "\" is already satisfied.");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
uris.Add(new Uri(packagePath));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Could not process dependency package at path \"" + dependency + "\"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = isSparsePackage
|
||||
? packageManager.AddPackageByUriAsync(new Uri(packagePath), new AddPackageOptions { ExternalLocationUri = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)! + "\\WinUi3Apps"), ForceUpdateFromAnyVersion = true })
|
||||
: packageManager.AddPackageAsync(new Uri(packagePath), uris, DeploymentOptions.ForceApplicationShutdown);
|
||||
deploymentOperation.Get();
|
||||
|
||||
switch (deploymentOperation.Status)
|
||||
{
|
||||
case AsyncStatus.Error:
|
||||
Logger.LogError($"Registering {packagePath} failed. ErrorCode: {deploymentOperation.ErrorCode}, ErrorText: {deploymentOperation.GetResults().ErrorText}");
|
||||
break;
|
||||
case AsyncStatus.Canceled:
|
||||
Logger.LogError($"Registering {packagePath} was canceled.");
|
||||
break;
|
||||
case AsyncStatus.Completed:
|
||||
Logger.LogInfo($"Registering {packagePath} succeded.");
|
||||
break;
|
||||
default:
|
||||
Logger.LogDebug($"Registering {packagePath} package started.");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception thrown while trying to register package: {packagePath}", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the package specified by the given path is already installed and satisfies the required version.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package.</param>
|
||||
/// <returns>True if the package is already installed and satisfies the required version, false otherwise.</returns>
|
||||
private static bool IsPackageSatisfied(string packagePath)
|
||||
{
|
||||
if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version))
|
||||
{
|
||||
Logger.LogError("Could not get package name and version from dependency package at path \"" + packagePath + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
PackageManager packageManager = new();
|
||||
|
||||
foreach (var package in packageManager.FindPackagesForUser(null))
|
||||
{
|
||||
if (package.Id.Name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
|
||||
package.Id.Version.ToVersion() >= version.ToVersion())
|
||||
{
|
||||
Logger.LogInfo($@"Package ""{name}"" is already statisfied with version: {package.Id.Version}. Target version: {version}. PackagePath: {packagePath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInfo($@"Package ""{name}"" with version {version} is not satisfied. PackagePath: {packagePath}");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the package name and version from the specified appx package file.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package file.</param>
|
||||
/// <param name="name">Output parameter for the package name.</param>
|
||||
/// <param name="packageVersion">Output parameter for the package version.</param>
|
||||
/// <returns>True if the package name and version were successfully retrieved, false otherwise.</returns>
|
||||
private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion)
|
||||
{
|
||||
bool retValue = PowerToys.Interop.Package.GetPackageNameAndVersionFromAppx(packagePath, out name, out PowerToys.Interop.PACKAGE_VERSION packageVersionInterop);
|
||||
packageVersion = new PackageVersion
|
||||
{
|
||||
Major = packageVersionInterop.Major,
|
||||
Minor = packageVersionInterop.Minor,
|
||||
Build = packageVersionInterop.Build,
|
||||
Revision = packageVersionInterop.Revision,
|
||||
};
|
||||
return retValue;
|
||||
}
|
||||
|
||||
[GeneratedRegex("(^.+\\.(appx|msix|msixbundle)$)", RegexOptions.IgnoreCase)]
|
||||
private static partial Regex msixPackagePattern();
|
||||
}
|
||||
}
|
||||
30
src/RunnerV2/RunnerV2/Helpers/ProcessHelper.cs
Normal file
30
src/RunnerV2/RunnerV2/Helpers/ProcessHelper.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class ProcessHelper
|
||||
{
|
||||
internal static void ScheudleProcessKill(string processName, int msDelay = 500)
|
||||
{
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(processName);
|
||||
|
||||
await Task.Delay(msDelay);
|
||||
foreach (var process in processes)
|
||||
{
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
99
src/RunnerV2/RunnerV2/Helpers/QuickAccessHelper.cs
Normal file
99
src/RunnerV2/RunnerV2/Helpers/QuickAccessHelper.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class QuickAccessHelper
|
||||
{
|
||||
private static Process _process = new Process();
|
||||
private static EventWaitHandle _showEvent = new(false, EventResetMode.AutoReset, "Local\\PowerToysQuickAccess__Show");
|
||||
private static EventWaitHandle _exitEvent = new(false, EventResetMode.AutoReset, "Local\\PowerToysQuickAccess__Exit");
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Starting Quick Access");
|
||||
|
||||
lock (_process)
|
||||
{
|
||||
string runnerPipeName = "\\\\.\\pipe\\powertoys_quick_access_runner_" + Guid.NewGuid();
|
||||
string appPipeName = "\\\\.\\pipe\\powertoys_quick_access_ui_" + Guid.NewGuid();
|
||||
|
||||
PowerToys.Interop.TwoWayPipeMessageIPCManaged quickAccessIpc = new(runnerPipeName, appPipeName, SettingsHelper.OnSettingsMessageReceived);
|
||||
quickAccessIpc.Start();
|
||||
|
||||
string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WinUI3Apps\\PowerToys.QuickAccess.exe");
|
||||
|
||||
if (!File.Exists(exePath))
|
||||
{
|
||||
Logger.LogError($"Quick Access executable not found at path: {exePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
_process = new Process();
|
||||
_process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = $"--show-event=\"Local\\PowerToysQuickAccess__Show\" --exit-event=\"Local\\PowerToysQuickAccess__Exit\" --runner-pipe=\"{runnerPipeName}\" --app-pipe=\"{appPipeName}\"",
|
||||
};
|
||||
_process.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return !_process.HasExited;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Show()
|
||||
{
|
||||
Start();
|
||||
|
||||
_showEvent.Set();
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (!IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Stopping Quick Access");
|
||||
_exitEvent.Set();
|
||||
lock (_process)
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.WaitForExit(2000);
|
||||
}
|
||||
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
226
src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs
Normal file
226
src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using Update;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides helper methods to interact with the PowerToys Settings window.
|
||||
/// </summary>
|
||||
internal static class SettingsHelper
|
||||
{
|
||||
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
|
||||
private static Process? _process;
|
||||
private static TwoWayPipeMessageIPCManaged? _ipc;
|
||||
|
||||
public static void OpenSettingsWindow(bool showOobeWindow = false, bool showScoobeWindow = false, string? additionalArguments = null)
|
||||
{
|
||||
if (_process is not null && _ipc is not null && !_process.HasExited)
|
||||
{
|
||||
_ipc.Send($@"{{""ShowYourself"": ""{additionalArguments ?? "Dashboard"}""}}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_ipc?.End();
|
||||
_ipc = null;
|
||||
|
||||
// Arg 1: Executable path
|
||||
string executablePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("No executable path found"), "WinUI3Apps", "PowerToys.Settings.exe");
|
||||
|
||||
// Arg 2,3: Pipe names
|
||||
Pipe settingsPipe = new();
|
||||
Pipe powertoysPipe = new();
|
||||
|
||||
string powerToysPipeName = @"\\.\pipe\powertoys_runner_" + Guid.NewGuid();
|
||||
string settingsPipeName = @"\\.\pipe\powertoys_settings_" + Guid.NewGuid();
|
||||
|
||||
// Arg 4: Process pid
|
||||
string currentProcessId = Environment.ProcessId.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
// Arg 5: Settings theme
|
||||
string theme = Program.GeneralSettings.Theme switch
|
||||
{
|
||||
"light" => "light",
|
||||
"dark" => "dark",
|
||||
"system" when ThemeHelpers.GetAppTheme() == AppTheme.Light => "light",
|
||||
"system" when ThemeHelpers.GetAppTheme() == AppTheme.Dark => "dark",
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
// Arg 6: Elevated status
|
||||
string isElevated = Program.GeneralSettings.IsElevated ? "true" : "false";
|
||||
|
||||
// Arg 7: Is user an administrator
|
||||
string isAdmin = Program.GeneralSettings.IsAdmin ? "true" : "false";
|
||||
|
||||
// Arg 8: Show OOBE window
|
||||
string showOobeArg = showOobeWindow ? "true" : "false";
|
||||
|
||||
// Arg 9: Show SCOOBE window
|
||||
string showScoobeArg = showScoobeWindow ? "true" : "false";
|
||||
|
||||
// Arg 10: Are there additional settings window arguments
|
||||
string areThereadditionalArgs = string.IsNullOrEmpty(additionalArguments) ? "false" : "true";
|
||||
|
||||
string executableArgs = $"{powerToysPipeName} {settingsPipeName} {currentProcessId} {theme} {isElevated} {isAdmin} {showOobeArg} {showScoobeArg} {areThereadditionalArgs}";
|
||||
|
||||
if (!string.IsNullOrEmpty(additionalArguments))
|
||||
{
|
||||
executableArgs += $" {additionalArguments}";
|
||||
}
|
||||
|
||||
Logger.LogInfo($"Starting Settings with arguments: {executableArgs}");
|
||||
|
||||
_process = Process.Start(executablePath, executableArgs);
|
||||
|
||||
// Initialize listening to pipes
|
||||
_ipc = new TwoWayPipeMessageIPCManaged(powerToysPipeName, settingsPipeName, OnSettingsMessageReceived);
|
||||
_ipc.Start();
|
||||
}
|
||||
|
||||
public static void OnSettingsMessageReceived(string message)
|
||||
{
|
||||
JsonDocument messageDocument = JsonDocument.Parse(message);
|
||||
|
||||
foreach (var property in messageDocument.RootElement.EnumerateObject())
|
||||
{
|
||||
switch (property.Name)
|
||||
{
|
||||
case "action":
|
||||
foreach (var moduleName in property.Value.EnumerateObject())
|
||||
{
|
||||
_settingsUtils.SaveSettings(moduleName.Value.ToString(), moduleName.Name);
|
||||
if (moduleName.Name == "general")
|
||||
{
|
||||
switch (moduleName.Value.GetProperty("action_name").GetString())
|
||||
{
|
||||
case "restart_elevation":
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevatedWithOpenSettings;
|
||||
Runner.Close();
|
||||
break;
|
||||
case "restart_mentain_elevation":
|
||||
// Todo:
|
||||
break;
|
||||
case "check_for_updates":
|
||||
UpdateSettingsHelper.TriggerUpdateCheck();
|
||||
break;
|
||||
case "request_update_state_date":
|
||||
// Todo:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (IPowerToysModule ptModule in Runner.LoadedModules)
|
||||
{
|
||||
if (ptModule.Name == moduleName.Name && ptModule is IPowerToysModuleCustomActionsProvider customActionsProvider && customActionsProvider.CustomActions.TryGetValue(moduleName.Value.GetProperty("action_name").GetString() ?? string.Empty, out Action<string>? action))
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
action(moduleName.Value.GetProperty("value").GetString() ?? string.Empty);
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "get_all_hotkey_conflicts":
|
||||
// Todo: Handle hotkey conflict
|
||||
break;
|
||||
case "bugreport":
|
||||
Logger.LogInfo("Starting bug report tool from Settings window");
|
||||
TrayIconManager.ProcessTrayMenuCommand((nuint)TrayIconManager.TrayButton.ReportBug);
|
||||
break;
|
||||
case "bug_report_status":
|
||||
_ipc?.Send($@"{{""bug_report_running"": {(TrayIconManager.IsBugReportToolRunning ? "true" : "false")}}}");
|
||||
break;
|
||||
case "killrunner":
|
||||
Runner.Close();
|
||||
break;
|
||||
case "general":
|
||||
try
|
||||
{
|
||||
_settingsUtils.SaveSettings(property.Value.ToString(), string.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed writing general settings from Settings window", ex);
|
||||
}
|
||||
|
||||
NativeMethods.PostMessageW(Runner.RunnerHwnd, (uint)NativeMethods.WindowMessages.REFRESH_SETTINGS, 0, 0);
|
||||
|
||||
foreach (IPowerToysModule module in Runner.ModulesToLoad)
|
||||
{
|
||||
if (module is IPowerToysModuleSettingsChangedSubscriber settingsChangedSubscriber)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + module.Name + "\\ModuleInterface\\Logs");
|
||||
settingsChangedSubscriber.OnSettingsChanged();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "powertoys":
|
||||
foreach (var powertoysSettingsPart in property.Value.EnumerateObject())
|
||||
{
|
||||
try
|
||||
{
|
||||
_settingsUtils.SaveSettings(powertoysSettingsPart.Value.ToString(), powertoysSettingsPart.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed writing {powertoysSettingsPart.Name} settings from Settings window", ex);
|
||||
}
|
||||
|
||||
if (Runner.LoadedModules.Find(m => m.Name == powertoysSettingsPart.Name) is IPowerToysModuleSettingsChangedSubscriber module && module is IPowerToysModule ptModule && ptModule.Enabled)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
module.OnSettingsChanged();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no specific module was found, notify all enabled modules
|
||||
foreach (IPowerToysModule module2 in Runner.LoadedModules.Where(m => m.Enabled))
|
||||
{
|
||||
if (module2 is IPowerToysModuleSettingsChangedSubscriber settingsChangedSubscriber)
|
||||
{
|
||||
settingsChangedSubscriber.OnSettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.PostMessageW(Runner.RunnerHwnd, (uint)NativeMethods.WindowMessages.REFRESH_SETTINGS, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"Unknown message received from Settings: {property.Name}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseSettingsWindow()
|
||||
{
|
||||
using var closeEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerToysRunnerTerminateSettingsEvent());
|
||||
closeEventWrapper.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
208
src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs
Normal file
208
src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static partial class TrayIconManager
|
||||
{
|
||||
private static bool _trayIconVisible;
|
||||
|
||||
private static nint GetTrayIcon()
|
||||
{
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowThemeAdaptiveTrayIcon)
|
||||
{
|
||||
return Icon.ExtractAssociatedIcon(ThemeHelper.GetCurrentSystemTheme() ? "./Assets/PowerToysDark.ico" : "./Assets/PowerToysLight.ico")!.Handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Icon.ExtractAssociatedIcon(Environment.ProcessPath!)!.Handle;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTrayIcon()
|
||||
{
|
||||
if (!_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = GetNOTIFYICONDATA();
|
||||
Shell_NotifyIcon(0x1, ref notifyicondata);
|
||||
}
|
||||
|
||||
private static NOTIFYICONDATA GetNOTIFYICONDATA() => new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf<NOTIFYICONDATA>(),
|
||||
HWnd = Runner.RunnerHwnd,
|
||||
UId = 1,
|
||||
HIcon = GetTrayIcon(),
|
||||
UFlags = 0x0000001 | 0x00000002 | 0x4,
|
||||
UCallbackMessage = (uint)WindowMessages.ICON_NOTIFY,
|
||||
SzTip = "PowerToys v" + Assembly.GetExecutingAssembly().GetName().Version!.Major + "." + Assembly.GetExecutingAssembly().GetName().Version!.Minor + "." + Assembly.GetExecutingAssembly().GetName().Version!.Build,
|
||||
};
|
||||
|
||||
internal static void StartTrayIcon()
|
||||
{
|
||||
if (_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = GetNOTIFYICONDATA();
|
||||
ChangeWindowMessageFilterEx(Runner.RunnerHwnd, 0x0111, 0x0001, IntPtr.Zero);
|
||||
|
||||
Shell_NotifyIcon(NIMADD, ref notifyicondata);
|
||||
_trayIconVisible = true;
|
||||
}
|
||||
|
||||
internal static void StopTrayIcon()
|
||||
{
|
||||
if (!_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf<NOTIFYICONDATA>(),
|
||||
HWnd = Runner.RunnerHwnd,
|
||||
UId = 1,
|
||||
};
|
||||
|
||||
Shell_NotifyIcon(NIMDELETE, ref notifyicondata);
|
||||
_trayIconVisible = false;
|
||||
}
|
||||
|
||||
internal enum TrayButton : uint
|
||||
{
|
||||
Settings = 1,
|
||||
Documentation,
|
||||
ReportBug,
|
||||
Close,
|
||||
}
|
||||
|
||||
private static bool _doubleClickTimerRunning;
|
||||
private static bool _doubleClickDetected;
|
||||
|
||||
private static IntPtr _trayIconMenu;
|
||||
|
||||
static TrayIconManager()
|
||||
{
|
||||
_trayIconMenu = CreatePopupMenu();
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Settings), "Settings\tDouble-click");
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Documentation), "Documentation");
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.ReportBug), "Report a Bug");
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Close), "Close");
|
||||
new ThemeListener().ThemeChanged += (_) =>
|
||||
{
|
||||
PostMessageW(Runner.RunnerHwnd, 0x0800, IntPtr.Zero, 0x9000);
|
||||
};
|
||||
}
|
||||
|
||||
internal static void ProcessTrayIconMessage(long lParam)
|
||||
{
|
||||
switch (lParam)
|
||||
{
|
||||
case 0x0205: // WM_RBUTTONDBLCLK
|
||||
case 0x007B: // WM_CONTEXTMENU
|
||||
SetForegroundWindow(Runner.RunnerHwnd);
|
||||
TrackPopupMenu(_trayIconMenu, 0x0004 | 0x0020, Cursor.Position.X, Cursor.Position.Y, 0, Runner.RunnerHwnd, IntPtr.Zero);
|
||||
break;
|
||||
case 0x0202: // WM_LBUTTONUP
|
||||
if (_doubleClickTimerRunning)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_doubleClickTimerRunning = true;
|
||||
Task.Delay(SystemInformation.DoubleClickTime).ContinueWith(_ =>
|
||||
{
|
||||
if (!_doubleClickDetected)
|
||||
{
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
QuickAccessHelper.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
}
|
||||
}
|
||||
|
||||
_doubleClickDetected = false;
|
||||
_doubleClickTimerRunning = false;
|
||||
});
|
||||
break;
|
||||
case 0x0203: // WM_LBUTTONDBLCLK
|
||||
_doubleClickDetected = true;
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
break;
|
||||
case 0x9000: // Update tray icon
|
||||
UpdateTrayIcon();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsBugReportToolRunning { get; set; }
|
||||
|
||||
internal static void ProcessTrayMenuCommand(nuint commandId)
|
||||
{
|
||||
switch ((TrayButton)commandId)
|
||||
{
|
||||
case TrayButton.Settings:
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
break;
|
||||
case TrayButton.Documentation:
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "https://aka.ms/PowerToysOverview",
|
||||
UseShellExecute = true,
|
||||
});
|
||||
break;
|
||||
case TrayButton.ReportBug:
|
||||
Logger.LogInfo("Starting bug report tool from tray menu");
|
||||
Process bugReportProcess = new();
|
||||
bugReportProcess.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "Tools\\PowerToys.BugReportTool.exe",
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
bugReportProcess.EnableRaisingEvents = true;
|
||||
|
||||
EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x000000 | 0x00001);
|
||||
|
||||
bugReportProcess.Exited += (sender, e) =>
|
||||
{
|
||||
bugReportProcess.Dispose();
|
||||
EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x00000000);
|
||||
IsBugReportToolRunning = false;
|
||||
Logger.LogInfo("Bug report tool exited");
|
||||
};
|
||||
|
||||
bugReportProcess.Start();
|
||||
IsBugReportToolRunning = true;
|
||||
|
||||
break;
|
||||
case TrayButton.Close:
|
||||
Runner.Close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/RunnerV2/RunnerV2/Models/IPowerToysModule.cs
Normal file
47
src/RunnerV2/RunnerV2/Models/IPowerToysModule.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
public interface IPowerToysModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the short name of the module. The same used as the name of the folder containing its settings.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the module is enabled.
|
||||
/// </summary>
|
||||
public void Enable();
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the module is disabled.
|
||||
/// </summary>
|
||||
public void Disable();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the module is enabled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value shall be read from the settings of the module in the module interface implementation.
|
||||
/// </remarks>
|
||||
public bool Enabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GPO rule configured state for the module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value shall be read from the GPO settings with the <see cref="GPOWrapper"/> class.
|
||||
/// </remarks>
|
||||
public GpoRuleConfigured GpoRuleConfigured { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleCustomActionsProvider
|
||||
{
|
||||
public Dictionary<string, Action<string>> CustomActions { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public void OnSettingsChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of shortcuts, that shall be registered in the keyboard hook, and their associated actions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this property is not overridden, the module is considered to not have shortcuts.
|
||||
/// </remarks>
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; }
|
||||
}
|
||||
}
|
||||
169
src/RunnerV2/RunnerV2/Models/ProcessModuleAbstractClass.cs
Normal file
169
src/RunnerV2/RunnerV2/Models/ProcessModuleAbstractClass.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using ManagedCommon;
|
||||
using RunnerV2.Helpers;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Base abstract class for modules that launch and manage external processes.
|
||||
/// </summary>
|
||||
internal abstract class ProcessModuleAbstractClass
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for launching a process.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ProcessLaunchOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Only a single instance of the process should be running.
|
||||
/// </summary>
|
||||
SingletonProcess = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Elevate the process if the current process is elevated.
|
||||
/// </summary>
|
||||
ElevateIfApplicable = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Provide the runner process ID as the first argument to the launched process.
|
||||
/// </summary>
|
||||
RunnerProcessIdAsFirstArgument = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the application should not launch automatically when the specified module is enabled.
|
||||
/// </summary>
|
||||
SupressLaunchOnModuleEnabled = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that the process should be started using the operating system shell.
|
||||
/// </summary>
|
||||
UseShellExecute = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the process should never exit automatically.
|
||||
/// </summary>
|
||||
/// <remarks>Use this value when using a helper process to launch an application like explorer.exe.</remarks>
|
||||
NeverExit = 32,
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses UI when process is launched.
|
||||
/// </summary>
|
||||
HideUI = 64,
|
||||
|
||||
/// <summary>
|
||||
/// Sets the launched process to realtime priority.
|
||||
/// </summary>
|
||||
RealtimePriority = 128,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the relative or absolute path to the process executable.
|
||||
/// </summary>
|
||||
public abstract string ProcessPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the process without the .exe extension.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Has no effect if the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.UseShellExecute"/> flag set.
|
||||
/// </remarks>
|
||||
public abstract string ProcessName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments to pass to the process on launch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If not overridden, no arguments are passed.
|
||||
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.RunnerProcessIdAsFirstArgument"/> flag is set, the runner process ID is prepended to these arguments.
|
||||
/// </remarks>
|
||||
public virtual string ProcessArguments { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options used to configure how the process is launched.
|
||||
/// </summary>
|
||||
public abstract ProcessLaunchOptions LaunchOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that atleast one process is launched. If the process is already running, does nothing.
|
||||
/// </summary>
|
||||
public void EnsureLaunched()
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(ProcessName);
|
||||
if (processes.Length > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LaunchProcess();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the process with the specified options.
|
||||
/// </summary>
|
||||
/// <param name="isModuleEnableProcess">Specifies if the <see cref="Runner"/> class is currently calling this function as part of a module startup</param>
|
||||
public void LaunchProcess(bool isModuleEnableProcess = false)
|
||||
{
|
||||
if (isModuleEnableProcess && LaunchOptions.HasFlag(ProcessLaunchOptions.SupressLaunchOnModuleEnabled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.SingletonProcess))
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(ProcessName);
|
||||
if (processes.Length > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string arguments = (LaunchOptions.HasFlag(ProcessLaunchOptions.RunnerProcessIdAsFirstArgument) ? Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + (string.IsNullOrEmpty(ProcessArguments) ? string.Empty : " ") : string.Empty) + ProcessArguments;
|
||||
|
||||
Process? p = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
UseShellExecute = LaunchOptions.HasFlag(ProcessLaunchOptions.UseShellExecute),
|
||||
FileName = ProcessPath,
|
||||
Arguments = arguments,
|
||||
Verb = LaunchOptions.HasFlag(ProcessLaunchOptions.ElevateIfApplicable) && ElevationHelper.IsProcessElevated() ? "runas" : "open",
|
||||
});
|
||||
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.RealtimePriority))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (p != null && !p.HasExited)
|
||||
{
|
||||
p.PriorityClass = ProcessPriorityClass.RealTime;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to set realtime priority for process {ProcessName}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schedules all processes with the specified <see cref="ProcessName"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.NeverExit"/> flag set, this function does nothing.
|
||||
/// </remarks>
|
||||
public void ProcessExit()
|
||||
{
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.NeverExit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessHelper.ScheudleProcessKill(ProcessName);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/RunnerV2/RunnerV2/Models/RegistryChangeSet.cs
Normal file
45
src/RunnerV2/RunnerV2/Models/RegistryChangeSet.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal readonly struct RegistryChangeSet
|
||||
{
|
||||
public RegistryValueChange[] Changes { get; init; }
|
||||
|
||||
public readonly bool IsApplied => Changes.All(c => c.IsApplied);
|
||||
|
||||
public readonly bool Apply()
|
||||
{
|
||||
bool allApplied = true;
|
||||
foreach (var change in Changes)
|
||||
{
|
||||
allApplied = (change.Apply() || !change.Required) && allApplied;
|
||||
}
|
||||
|
||||
return allApplied;
|
||||
}
|
||||
|
||||
public readonly bool ApplyIfNotApplied() => IsApplied || Apply();
|
||||
|
||||
public readonly bool UnApplyIfApplied() => !IsApplied || UnApply();
|
||||
|
||||
public readonly bool UnApply()
|
||||
{
|
||||
bool allUnapplied = true;
|
||||
foreach (var change in Changes)
|
||||
{
|
||||
allUnapplied = (change.UnApply() || !change.Required) && allUnapplied;
|
||||
}
|
||||
|
||||
return allUnapplied;
|
||||
}
|
||||
}
|
||||
}
|
||||
124
src/RunnerV2/RunnerV2/Models/RegistryValueChange.cs
Normal file
124
src/RunnerV2/RunnerV2/Models/RegistryValueChange.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal readonly struct RegistryValueChange
|
||||
{
|
||||
public RegistryValueChange()
|
||||
{
|
||||
}
|
||||
|
||||
public required string KeyPath { get; init; }
|
||||
|
||||
public required string? KeyName { get; init; }
|
||||
|
||||
public bool Required { get; init; } = true;
|
||||
|
||||
public required object Value { get; init; }
|
||||
|
||||
public RegistryHive Scope { get; init; } = RegistryHive.CurrentUser;
|
||||
|
||||
private static RegistryValueKind ValueTypeToRegistryValueKind(object value)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
int => RegistryValueKind.DWord,
|
||||
long => RegistryValueKind.QWord,
|
||||
string => RegistryValueKind.String,
|
||||
string[] => RegistryValueKind.MultiString,
|
||||
byte[] => RegistryValueKind.Binary,
|
||||
_ => throw new ArgumentException("Unsupported value type"),
|
||||
};
|
||||
}
|
||||
|
||||
public readonly bool IsApplied
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).OpenSubKey(KeyPath, false);
|
||||
return key != null && ValueTypeToRegistryValueKind(Value) == key.GetValueKind(KeyName) && Value.Equals(key.GetValue(KeyName));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Testing if registry change \"{this}\" is applied failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly bool RequiresElevation
|
||||
{
|
||||
get => Scope == RegistryHive.LocalMachine;
|
||||
}
|
||||
|
||||
public readonly bool Apply()
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).CreateSubKey(KeyPath, true);
|
||||
if (key == null)
|
||||
{
|
||||
Logger.LogError($"Applying registry change \"{this}\" failed because the registry key could not be created.");
|
||||
return false;
|
||||
}
|
||||
|
||||
key.SetValue(KeyName, Value, ValueTypeToRegistryValueKind(Value));
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Applying registry change \"{this}\" failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly bool UnApply()
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).OpenSubKey(KeyPath, true);
|
||||
if (key == null)
|
||||
{
|
||||
Logger.LogError($"Unapplying registry change \"{this}\" failed because the registry key could not be opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (KeyName is not null)
|
||||
{
|
||||
key.DeleteValue(KeyName, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
key.SetValue(null, string.Empty); // Delete the default value
|
||||
}
|
||||
|
||||
// Check if the path doesn't contain anything and delete it if so
|
||||
if (key.GetValueNames().Length == 0 && key.GetSubKeyNames().Length == 0)
|
||||
{
|
||||
RegistryKey.OpenBaseKey(Scope, RegistryView.Default).DeleteSubKey(KeyPath, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Unapplying registry change \"{this}\" failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override readonly string ToString() => $"{RegistryKey.OpenBaseKey(Scope, RegistryView.Default).Name}\\{KeyPath}\\{KeyName}:{Value}";
|
||||
}
|
||||
}
|
||||
16
src/RunnerV2/RunnerV2/Models/SpecialMode.cs
Normal file
16
src/RunnerV2/RunnerV2/Models/SpecialMode.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal enum SpecialMode
|
||||
{
|
||||
None,
|
||||
Win32ToastNotificationCOMServer,
|
||||
DisableCantDragElevatedNotification,
|
||||
UpdateNow,
|
||||
ReportSuccessfulUpdate,
|
||||
CouldntToggleFileExplorerModulesNotification,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AdvancedPasteModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "AdvancedPaste";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.AdvancedPaste;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAdvancedPasteEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (_ipc != null)
|
||||
{
|
||||
_ipc.Send(Constants.AdvancedPasteTerminateAppMessage());
|
||||
_ipc.End();
|
||||
_ipc = null;
|
||||
}
|
||||
}
|
||||
|
||||
private const string IpcName = @"\\.\pipe\PowerToys.AdvancedPaste";
|
||||
private TwoWayPipeMessageIPCManaged? _ipc;
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
_ipc = new TwoWayPipeMessageIPCManaged(@"\\.\pipe\PowerToys.AdvancedPast.Input", IpcName, (_) => { });
|
||||
_ipc.Start();
|
||||
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
_ipc ??= new TwoWayPipeMessageIPCManaged(@"\\.\pipe\PowerToys.AdvancedPast.Input", @"\\.\pipe\PowerToys.AdvancedPaste", (_) => { });
|
||||
|
||||
Shortcuts.Clear();
|
||||
|
||||
AdvancedPasteSettings settings = SettingsUtils.Default.GetSettingsOrDefault<AdvancedPasteSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.AdvancedPasteUIShortcut, () =>
|
||||
_ipc.Send(Constants.AdvancedPasteShowUIMessage())
|
||||
));
|
||||
Shortcuts.Add((settings.Properties.PasteAsPlainTextShortcut, TryToPasteAsPlainText));
|
||||
Shortcuts.Add((settings.Properties.PasteAsMarkdownShortcut, () => _ipc.Send(Constants.AdvancedPasteMarkdownMessage())));
|
||||
Shortcuts.Add((settings.Properties.PasteAsJsonShortcut, () => _ipc.Send(Constants.AdvancedPasteJsonMessage())));
|
||||
|
||||
HotkeyAccessor[] hotkeyAccessors = settings.GetAllHotkeyAccessors();
|
||||
int additionalActionsCount = settings.Properties.AdditionalActions.GetAllActions().Count() - 2;
|
||||
for (int i = 0; i < additionalActionsCount; i++)
|
||||
{
|
||||
int scopedI = i;
|
||||
Shortcuts.Add((hotkeyAccessors[4 + i].Value, () => _ipc.Send(Constants.AdvancedPasteAdditionalActionMessage() + " " + (3 + scopedI))));
|
||||
}
|
||||
|
||||
for (int i = 4 + additionalActionsCount; i < hotkeyAccessors.Length; i++)
|
||||
{
|
||||
int scopedI = i;
|
||||
Shortcuts.Add((hotkeyAccessors[i].Value, () => _ipc.Send(Constants.AdvancedPasteCustomActionMessage() + " " + (scopedI - 4 - additionalActionsCount))));
|
||||
}
|
||||
}
|
||||
|
||||
private void TryToPasteAsPlainText()
|
||||
{
|
||||
PowerToys.Interop.Clipboard.PasteAsPlainText();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ipc?.Dispose();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.AdvancedPaste.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.AdvancedPaste";
|
||||
|
||||
public override string ProcessArguments => IpcName;
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AlwaysOnTopModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.AlwaysOnTop;
|
||||
|
||||
public string Name => "AlwaysOnTop";
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AlwaysOnTopTerminateEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeHotkey();
|
||||
}
|
||||
|
||||
private void InitializeHotkey()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<AlwaysOnTopSettings>(Name).Properties.Hotkey.Value, () =>
|
||||
{
|
||||
using var pinEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AlwaysOnTopPinEvent());
|
||||
pinEventWrapper.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeHotkey();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.AlwaysOnTop.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.AlwaysOnTop";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.ElevateIfApplicable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AwakeModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "Awake";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Awake;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAwakeEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.Awake.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Awake";
|
||||
|
||||
public override string ProcessArguments => $"--use-pt-config --pid {Environment.ProcessId.ToString(CultureInfo.InvariantCulture)}";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AwakeExitEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CmdNotFoundModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "CmdNotFound";
|
||||
|
||||
public bool Enabled => true;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
|
||||
|
||||
public CmdNotFoundModuleInterface()
|
||||
{
|
||||
if (GpoRuleConfigured == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
UninstallModule();
|
||||
}
|
||||
|
||||
if (GpoRuleConfigured == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
InstallModule();
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallModule()
|
||||
{
|
||||
Logger.LogInfo("Installing Command Not Found module invoked through GPO");
|
||||
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process p = Process.Start("pwsh.exe", "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\EnableModule.ps1" + "\"" + " -scriptPath \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\"");
|
||||
await p.WaitForExitAsync();
|
||||
if (p.ExitCode == 0)
|
||||
{
|
||||
Logger.LogInfo("Command Not Found was successfully installed.");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Command Not Found failed to install with exit code: " + p.ExitCode);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void UninstallModule()
|
||||
{
|
||||
Logger.LogInfo("Uninstalling Command Not Found module invoked through GPO");
|
||||
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process p = Process.Start("pwsh.exe", "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"" + " -scriptPath \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\"");
|
||||
await p.WaitForExitAsync();
|
||||
if (p.ExitCode == 0)
|
||||
{
|
||||
Logger.LogInfo("Command Not Found was successfully uninstalled.");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Command Not Found failed to uninstall with exit code: " + p.ExitCode);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ColorPickerModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "ColorPicker";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.ColorPicker;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredColorPickerEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminateColorPickerSharedEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<ColorPickerSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
using var showUiEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent());
|
||||
showUiEventWrapper.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.ColorPickerUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ColorPickerUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CommandPaletteModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
private const string PackageName = "Microsoft.CommandPalette"
|
||||
#if DEBUG
|
||||
+ ".Dev"
|
||||
#endif
|
||||
;
|
||||
|
||||
public string Name => "CmdPal";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.CmdPal;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCmdPalEnabledValue();
|
||||
|
||||
public override string ProcessPath => "explorer.exe";
|
||||
|
||||
public override string ProcessArguments => "x-cmdpal://background";
|
||||
|
||||
public override string ProcessName => string.Empty;
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.UseShellExecute | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
if (PackageHelper.GetRegisteredPackage(PackageName, false) is null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string architectureString = RuntimeInformation.ProcessArchitecture == Architecture.X64 ? "x64" : "ARM64";
|
||||
#if DEBUG
|
||||
string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\", false);
|
||||
string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\Dependencies\\" + architectureString + "\\", true);
|
||||
#else
|
||||
string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\", false);
|
||||
string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\Dependencies\\", true);
|
||||
#endif
|
||||
|
||||
if (msixFiles.Length > 0)
|
||||
{
|
||||
if (!PackageHelper.InstallPackage(msixFiles[0], dependencies))
|
||||
{
|
||||
Logger.LogError("Failed to register Command Palette package.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Exception occurred while enabling Command Palette package.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (PackageHelper.GetRegisteredPackage(PackageName, false) is null)
|
||||
{
|
||||
Logger.LogError("Command Palette package is not registered after attempting to enable it.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class CropAndLockModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "CropAndLock";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.CropAndLock;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCropAndLockEnabledValue();
|
||||
|
||||
private EventWaitHandle _reparentEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockReparentEvent());
|
||||
private EventWaitHandle _thumbnailEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockThumbnailEvent());
|
||||
private EventWaitHandle _terminateEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockExitEvent());
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<CropAndLockSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.ThumbnailHotkey.Value, () => _thumbnailEvent.Set()));
|
||||
Shortcuts.Add((settings.Properties.ReparentHotkey.Value, () => _reparentEvent.Set()));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.CropAndLock.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.CropAndLock";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_reparentEvent.Dispose();
|
||||
_thumbnailEvent.Dispose();
|
||||
_terminateEvent.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CursorWrapModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "CursorWrap";
|
||||
|
||||
private bool _hookActive;
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.CursorWrap;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCursorWrapEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_hookActive = false;
|
||||
CursorWrapStopMouseHook();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
_hookActive = true;
|
||||
CursorWrapStartMouseHook();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<CursorWrapSettings>(Name).Properties.DefaultActivationShortcut, () =>
|
||||
{
|
||||
if (_hookActive)
|
||||
{
|
||||
CursorWrapStopMouseHook();
|
||||
_hookActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CursorWrapStartMouseHook();
|
||||
_hookActive = true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
[DllImport("PowerToys.CursorWrap.dll")]
|
||||
private static extern bool CursorWrapStartMouseHook();
|
||||
|
||||
[DllImport("PowerToys.CursorWrap.dll")]
|
||||
private static extern bool CursorWrapStopMouseHook();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class EnvironmentVariablesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "Environment Variables";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.EnvironmentVariables;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.EnvironmentVariables.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.EnvironmentVariables";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FancyZonesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "FancyZones";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FancyZones;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFancyZonesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.FancyZones.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.FancyZones";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.HideUI;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEExitEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions => new()
|
||||
{
|
||||
{
|
||||
"ToggledFZEditor",
|
||||
(_) =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeFZEditorEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEToggleEvent());
|
||||
invokeFZEditorEvent.Set();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<FancyZonesSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.FancyzonesEditorHotkey.Value, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeFZEditorEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEToggleEvent());
|
||||
invokeFZEditorEvent.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FileExplorerModuleInterface : IPowerToysModule, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
private record struct FileExplorerModule(Func<bool> IsEnabled, GpoRuleConfigured GpoRule, RegistryChangeSet RegistryChanges);
|
||||
|
||||
private static readonly List<FileExplorerModule> _fileExplorerModules;
|
||||
|
||||
private static readonly string[] ExtSVG = { ".svg" };
|
||||
private static readonly string[] ExtMarkdown = { ".md", ".markdown", ".mdown", ".mkdn", ".mkd", ".mdwn", ".mdtxt", ".mdtext" };
|
||||
private static readonly string[] ExtPDF = { ".pdf" };
|
||||
private static readonly string[] ExtGCode = { ".gcode" };
|
||||
private static readonly string[] ExtBGCode = { ".bgcode" };
|
||||
private static readonly string[] ExtSTL = { ".stl" };
|
||||
private static readonly string[] ExtQOI = { ".qoi" };
|
||||
|
||||
static FileExplorerModuleInterface()
|
||||
{
|
||||
static PowerPreviewProperties GetProperties() => SettingsUtils.Default.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName).Properties;
|
||||
|
||||
string installationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
_fileExplorerModules = [
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableBgcodePreview,
|
||||
GPOWrapper.GetConfiguredBgcodePreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{0e6d5bdd-d5f8-4692-a089-8bb88cdd37f4}", "BgcodePreviewHandler", "Binary G-code Preview Handler", ExtBGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableBgcodeThumbnail,
|
||||
GPOWrapper.GetConfiguredBgcodeThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{5c93a1e4-99d0-4fb3-991c-6c296a27be21}", "BgcodeThumbnailProvider", "Binary G-code Thumbnail Provider", ExtBGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableGcodePreview,
|
||||
GPOWrapper.GetConfiguredGcodePreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{A0257634-8812-4CE8-AF11-FA69ACAEAFAE}", "GcodePreviewHandler", "G-code Preview Handler", ExtGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableGcodeThumbnail,
|
||||
GPOWrapper.GetConfiguredGcodeThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{F2847CBE-CD03-4C83-A359-1A8052C1B9D5}", "GcodeThumbnailProvider", "G-code Thumbnail Provider", ExtGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableMdPreview,
|
||||
GPOWrapper.GetConfiguredMarkdownPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{60789D87-9C3C-44AF-B18C-3DE2C2820ED3}", "MarkdownPreviewHandler", "Markdown Preview Handler", ExtMarkdown)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnablePdfPreview,
|
||||
GPOWrapper.GetConfiguredPdfPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{A5A41CC7-02CB-41D4-8C9B-9087040D6098}", "PdfPreviewHandler", "PDF Preview Handler", ExtPDF)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnablePdfThumbnail,
|
||||
GPOWrapper.GetConfiguredPdfThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{D8BB9942-93BD-412D-87E4-33FAB214DC1A}", "PdfThumbnailProvider", "PDF Thumbnail Provider", ExtPDF)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableQoiPreview,
|
||||
GPOWrapper.GetConfiguredQoiPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{729B72CD-B72E-4FE9-BCBF-E954B33FE699}", "QoiPreviewHandler", "QOI Preview Handler", ExtQOI)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableQoiThumbnail,
|
||||
GPOWrapper.GetConfiguredQoiThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{AD856B15-D25E-4008-AFB7-AFAA55586188}", "QoiThumbnailProvider", "QOI Thumbnail Provider", ExtQOI, "image", "Picture")),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableStlThumbnail,
|
||||
GPOWrapper.GetConfiguredStlThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{77257004-6F25-4521-B602-50ECC6EC62A6}", "StlThumbnailProvider", "STL Thumbnail Provider", ExtSTL)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableSvgPreview,
|
||||
GPOWrapper.GetConfiguredSvgPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{FCDD4EED-41AA-492F-8A84-31A1546226E0}", "SvgPreviewHandler", "SVG Preview Handler", ExtSVG)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableSvgThumbnail,
|
||||
GPOWrapper.GetConfiguredSvgThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{10144713-1526-46C9-88DA-1FB52807A9FF}", "SvgThumbnailProvider", "SVG Thumbnail Provider", ExtSVG, "image", "Picture")),
|
||||
GetMonacoFileExplorerModule(installationPath)
|
||||
];
|
||||
}
|
||||
|
||||
private static FileExplorerModule GetMonacoFileExplorerModule(string installationPath)
|
||||
{
|
||||
// .svgz is a binary file type that Monaco cannot handle, so we exclude it from the preview handler
|
||||
string[] extExclusions = [..ExtMarkdown, ..ExtSVG, ".svgz"];
|
||||
List<string> extensions = [];
|
||||
|
||||
string languagesFilePath = Path.Combine(installationPath, "Assets\\Monaco\\monaco_languages.json");
|
||||
|
||||
if (!File.Exists(languagesFilePath))
|
||||
{
|
||||
Logger.LogError("PowerPreviewModuleInterface: Unable to find monaco_languages.json file at " + languagesFilePath);
|
||||
goto returnLabel;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
JsonDocument jsonDocument = JsonDocument.Parse(File.ReadAllText(languagesFilePath));
|
||||
var list = jsonDocument.RootElement.GetProperty("list");
|
||||
|
||||
foreach (var item in list.EnumerateArray())
|
||||
{
|
||||
if (item.TryGetProperty("extensions", out JsonElement extensionsElement))
|
||||
{
|
||||
foreach (var ext in extensionsElement.EnumerateArray())
|
||||
{
|
||||
string extension = ext.GetString() ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(extension) && !extensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
extensions.Add(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("PowerPreviewModuleInterface: Failed to parse monaco_languages.json file.", ex);
|
||||
}
|
||||
|
||||
returnLabel:
|
||||
return new FileExplorerModule(
|
||||
() => SettingsUtils.Default.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName).Properties.EnableMonacoPreview,
|
||||
GPOWrapper.GetConfiguredMonacoPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(
|
||||
FileExplorerAddOnType.PreviewHandler,
|
||||
"{D8034CFA-F34B-41FE-AD45-62FCBB52A6DA}",
|
||||
"MonacoPreviewHandler",
|
||||
"Monaco Preview Handler",
|
||||
[.. extensions.Where(ext => !extExclusions.Contains(ext))]));
|
||||
}
|
||||
|
||||
private enum FileExplorerAddOnType
|
||||
{
|
||||
ThumbnailProvider,
|
||||
PreviewHandler,
|
||||
}
|
||||
|
||||
private static RegistryChangeSet GetFileExplorerAddOnChangeSet(FileExplorerAddOnType type, string handlerClsid, string className, string displayName, string[] fileTypes, string? perceivedType = null, string? fileKindType = null)
|
||||
{
|
||||
string installationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
string pathToHandler = Path.Combine(installationPath, "PowerToys.FileExplorerDllExporter.dll");
|
||||
string clsidPath = "Software\\Classes\\CLSID\\" + handlerClsid;
|
||||
string inprocServer32Path = clsidPath + "\\InprocServer32";
|
||||
|
||||
string assemblyKeyValue;
|
||||
int lastDotPos = className.LastIndexOf('.');
|
||||
|
||||
if (lastDotPos != -1)
|
||||
{
|
||||
assemblyKeyValue = string.Concat("PowerToys.", className.AsSpan(lastDotPos + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblyKeyValue = "PowerToys." + className;
|
||||
}
|
||||
|
||||
assemblyKeyValue += $", Version={Assembly.GetExecutingAssembly().GetName().Version!}, Culture=neutral";
|
||||
|
||||
List<RegistryValueChange> changes = [
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = "DisplayName",
|
||||
Value = displayName,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = null,
|
||||
Value = className,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = null,
|
||||
Value = pathToHandler,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "Assembly",
|
||||
Value = assemblyKeyValue,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "Class",
|
||||
Value = className,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "ThreadingModel",
|
||||
Value = "Apartment",
|
||||
},
|
||||
];
|
||||
|
||||
foreach (string fileType in fileTypes)
|
||||
{
|
||||
string fileTypePath = "Software\\Classes\\" + fileType;
|
||||
string fileAssociationPath = fileTypePath + "\\shellex\\" + (type == FileExplorerAddOnType.PreviewHandler ? IPREVIEWHANDLERCLSID : ITHUMBNAILPROVIDERCLSID);
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = fileAssociationPath,
|
||||
KeyName = null,
|
||||
Value = handlerClsid,
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(fileKindType))
|
||||
{
|
||||
// Registering a file type as a kind needs to be done at the HKEY_LOCAL_MACHINE level.
|
||||
// Make it optional as well so that we don't fail registering the handler if we can't write to HKEY_LOCAL_MACHINE.
|
||||
string kindPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\KindMap";
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
Scope = Microsoft.Win32.RegistryHive.LocalMachine,
|
||||
KeyPath = kindPath,
|
||||
KeyName = fileType,
|
||||
Value = fileKindType,
|
||||
Required = false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(perceivedType))
|
||||
{
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = fileTypePath,
|
||||
KeyName = "PerceivedType",
|
||||
Value = perceivedType,
|
||||
});
|
||||
}
|
||||
|
||||
// this regfile registry key has precedence over Software\Classes\.reg for .reg files
|
||||
if (type == FileExplorerAddOnType.PreviewHandler && fileType.Equals(".reg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string regFilePath = "Software\\Classes\\regfile\\shellex\\" + IPREVIEWHANDLERCLSID;
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = regFilePath,
|
||||
KeyName = null,
|
||||
Value = handlerClsid,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (type == FileExplorerAddOnType.PreviewHandler)
|
||||
{
|
||||
string previewHostClsid = "{6d2b5079-2f0b-48dd-ab7f-97cec514d30b}";
|
||||
string previewHandlerListPath = "(Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers)";
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = "AppID",
|
||||
Value = previewHostClsid,
|
||||
});
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = previewHandlerListPath,
|
||||
KeyName = handlerClsid,
|
||||
Value = displayName,
|
||||
});
|
||||
}
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
Scope = Microsoft.Win32.RegistryHive.LocalMachine,
|
||||
KeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
|
||||
KeyName = handlerClsid,
|
||||
Value = displayName,
|
||||
Required = false,
|
||||
});
|
||||
|
||||
return new RegistryChangeSet
|
||||
{
|
||||
Changes = [.. changes],
|
||||
};
|
||||
}
|
||||
|
||||
private const string ITHUMBNAILPROVIDERCLSID = "{E357FCCD-A995-4576-B01F-234630154E96}";
|
||||
private const string IPREVIEWHANDLERCLSID = "{8895b1c6-b41f-4c1c-a562-0d564250836f}";
|
||||
|
||||
public string Name => "File Explorer";
|
||||
|
||||
public bool Enabled => true;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GpoRuleConfigured.Unavailable;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
foreach (FileExplorerModule submodule in _fileExplorerModules)
|
||||
{
|
||||
if (submodule.GpoRule == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
submodule.RegistryChanges.UnApply();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (submodule.IsEnabled() || submodule.GpoRule == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
submodule.RegistryChanges.Apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
submodule.RegistryChanges.UnApply();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class FileLocksmithModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "FileLocksmith";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FileLocksmith;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFileLocksmithEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateFileLocksmithRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateFileLocksmithRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "FileLocksmithContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.FileLocksmithExt.dll")]
|
||||
private static partial void UpdateFileLocksmithRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FindMyMouseModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "FindMyMouse";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FindMyMouse;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
FindMyMouseDisable();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
|
||||
var thread = new Thread(() =>
|
||||
{
|
||||
uint version = 0x00010008;
|
||||
int hr = MddBootstrapInitialize(version, 0, IntPtr.Zero);
|
||||
if (hr < 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Windows app sdk could not be initialized for MouseJump. HR code:{hr}");
|
||||
}
|
||||
|
||||
FindMyMouseMain();
|
||||
});
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
NativeMethods.PostMessageW(GetSonarHwnd(), GetWmPrivSettingsChanged(), IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<FindMyMouseSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
NativeMethods.PostMessageW(GetSonarHwnd(), GetWmPrivShortcut(), IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern void FindMyMouseMain();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern void FindMyMouseDisable();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern IntPtr GetSonarHwnd();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern uint GetWmPrivShortcut();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern uint GetWmPrivSettingsChanged();
|
||||
|
||||
[DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern int MddBootstrapInitialize(uint majorMinorVersion, uint versionTag, IntPtr packageVersion);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class HostsModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.Hosts;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
|
||||
|
||||
public string Name => "Hosts";
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.Hosts.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Hosts";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class ImageResizerModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "ImageResizer";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ImageResizer;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredImageResizerEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateImageResizerRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateImageResizerRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "ImageResizerContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.ImageResizerExt.dll")]
|
||||
private static partial void UpdateImageResizerRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class KeyboardManagerModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "Keyboard Manager";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.KeyboardManager;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredKeyboardManagerEnabledValue();
|
||||
|
||||
public override string ProcessPath => "KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.KeyboardManagerEngine";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.RealtimePriority;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminateKBMSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class LightSwitchModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
public string Name => "LightSwitch";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.LightSwitch;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredLightSwitchEnabledValue();
|
||||
|
||||
public override string ProcessPath => "LightSwitchService\\PowerToys.LightSwitchService.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.LightSwitchService";
|
||||
|
||||
public override string ProcessArguments => $"--pid {Environment.ProcessId}";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts
|
||||
{
|
||||
get => [(SettingsUtils.Default.GetSettings<LightSwitchSettings>(Name).Properties.ToggleThemeHotkey.Value, () =>
|
||||
{
|
||||
LightSwitchProperties properties = SettingsUtils.Default.GetSettings<LightSwitchSettings>(Name).Properties;
|
||||
EnsureLaunched();
|
||||
if (properties.ChangeSystem.Value)
|
||||
{
|
||||
ThemeHelper.SetSystemTheme(!ThemeHelper.GetCurrentSystemTheme());
|
||||
}
|
||||
|
||||
if (properties.ChangeApps.Value)
|
||||
{
|
||||
ThemeHelper.SetAppsTheme(!ThemeHelper.GetCurrentAppsTheme());
|
||||
}
|
||||
|
||||
using var manualOverrideEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.LightSwitchManualOverrideEvent());
|
||||
manualOverrideEvent.Set();
|
||||
})];
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class MeasureToolModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Measure Tool";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MeasureTool;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredScreenRulerEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.MeasureToolUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MeasureToolUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SupressLaunchOnModuleEnabled;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<MeasureToolSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
LaunchProcess();
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class MouseHighlighterModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MouseHighlighter";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseHighlighter;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
DisableMouseHighlighter();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
EnableMouseHighlighter();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<MouseHighlighterSettings>(Name).Properties.ActivationShortcut, ToggleMouseHighlighter));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
MouseHighlighterSettingsChanged();
|
||||
}
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void DisableMouseHighlighter();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void EnableMouseHighlighter();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void MouseHighlighterSettingsChanged();
|
||||
|
||||
[LibraryImport("PowerToys.MouseHighlighter.dll")]
|
||||
internal static partial void ToggleMouseHighlighter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class MouseJumpModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MouseJump";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseJump;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseJumpEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.MouseJumpUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MouseJumpUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.TerminateMouseJumpSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseJumpSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.ActivationShortcut, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeMouseJumpEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.MouseJumpShowPreviewEvent());
|
||||
invokeMouseJumpEvent.Set();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class MousePointerCrosshairsModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "MousePointerCrosshairs";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MousePointerCrosshairs;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
DisableMousePointerCrosshairs();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
EnableMousePointerCrosshairs();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<MousePointerCrosshairsSettings>(Name).Properties;
|
||||
Shortcuts.Add((settings.ActivationShortcut, OnMousePointerCrosshairsActivationShortcut));
|
||||
Shortcuts.Add((settings.GlidingCursorActivationShortcut, OnMousePointerCrosshairsGlidingCursorShortcut));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
OnMousePointerCrosshairsSettingsChanged();
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void DisableMousePointerCrosshairs();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void EnableMousePointerCrosshairs();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsSettingsChanged();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsActivationShortcut();
|
||||
|
||||
[LibraryImport("PowerToys.MousePointerCrosshairs.dll")]
|
||||
internal static partial void OnMousePointerCrosshairsGlidingCursorShortcut();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceProcess;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class MouseWithoutBordersModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleSettingsChangedSubscriber, IPowerToysModuleCustomActionsProvider
|
||||
{
|
||||
public string Name => "MouseWithoutBorders";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MouseWithoutBorders;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.MouseWithoutBorders.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MouseWithoutBorders";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public override string ProcessArguments
|
||||
{
|
||||
get
|
||||
{
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseWithoutBordersSettings>();
|
||||
return settings.Properties.UseService ? " UseService" : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions => new()
|
||||
{
|
||||
{ "add_firewall", (_) => LaunchAddFirewallProcess() },
|
||||
{ "uninstall_service", (_) => { new Thread(UnregisterService).Start(); } },
|
||||
};
|
||||
|
||||
private void RegisterService()
|
||||
{
|
||||
IntPtr schSCManager = NativeMethods.OpenSCManagerW(string.Empty, "ServicesActive", NativeMethods.SCMANAGERALLACCESS);
|
||||
if (schSCManager == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open Service Control Manager");
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr hService = NativeMethods.OpenServiceW(schSCManager, "PowerToys.MWB.Service", 0x0004 | 0x0001 | 0x0002);
|
||||
|
||||
string servicePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "PowerToys.MouseWithoutBordersService.exe");
|
||||
|
||||
IntPtr pServiceConfig = IntPtr.Zero;
|
||||
if (!NativeMethods.QueryServiceConfigW(hService, IntPtr.Zero, 0, out uint bytesNeeded))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == 122)
|
||||
{
|
||||
pServiceConfig = Marshal.AllocHGlobal((int)bytesNeeded);
|
||||
if (!NativeMethods.QueryServiceConfigW(hService, pServiceConfig, bytesNeeded, out _))
|
||||
{
|
||||
Marshal.FreeHGlobal(pServiceConfig);
|
||||
pServiceConfig = IntPtr.Zero;
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool alreadyRegistered = false;
|
||||
bool isServicePathCorrect = true;
|
||||
|
||||
string EscapeDoubleQuotes(string input)
|
||||
{
|
||||
StringBuilder output = new(input.Length);
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (c == '"')
|
||||
{
|
||||
output.Append('\\');
|
||||
}
|
||||
|
||||
output.Append(c);
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
string expectedPath = "\"" + servicePath + "\" " + EscapeDoubleQuotes(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
|
||||
|
||||
if (pServiceConfig != IntPtr.Zero)
|
||||
{
|
||||
alreadyRegistered = true;
|
||||
var serviceConfig = Marshal.PtrToStructure<NativeMethods.QueryServiceConfig>(pServiceConfig);
|
||||
string currentPath = serviceConfig.lpBinaryPathName;
|
||||
|
||||
if (currentPath != expectedPath)
|
||||
{
|
||||
Logger.LogInfo($"MWB Service path is incorrect. Current: {currentPath} Expected: {expectedPath}");
|
||||
}
|
||||
|
||||
if (serviceConfig.dwStartType == 0x0004)
|
||||
{
|
||||
if (!NativeMethods.ChangeServiceConfigW(hService, 0xffffffff, 0x3, 0xffffffff, null!, null!, IntPtr.Zero, null!, null!, null!, null!))
|
||||
{
|
||||
// Check if marked for delete
|
||||
if (Marshal.GetLastWin32Error() == 1072)
|
||||
{
|
||||
alreadyRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(pServiceConfig);
|
||||
}
|
||||
|
||||
if (alreadyRegistered)
|
||||
{
|
||||
if (!isServicePathCorrect)
|
||||
{
|
||||
if (!NativeMethods.ChangeServiceConfigW(hService, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, expectedPath, null!, IntPtr.Zero, null!, null!, null!, null!))
|
||||
{
|
||||
Logger.LogError("Couldn't update MWB Service path");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInfo("MWB Service path updated successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hService = NativeMethods.CreateServiceW(
|
||||
schSCManager,
|
||||
"PowerToys.MWB.Service",
|
||||
"PowerToys.MWB.Service",
|
||||
NativeMethods.SERVICEALLACCESS,
|
||||
0x00000010,
|
||||
0x00000003,
|
||||
0x00000001,
|
||||
expectedPath,
|
||||
null!,
|
||||
IntPtr.Zero,
|
||||
null!,
|
||||
null!,
|
||||
null!);
|
||||
|
||||
if (hService == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't create MWB Service");
|
||||
return;
|
||||
}
|
||||
|
||||
string sid = WindowsIdentity.GetCurrent().User!.Value;
|
||||
|
||||
string securityDescriptor = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWPDTLO;;;"
|
||||
+ sid
|
||||
+ ")S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)";
|
||||
|
||||
if (!NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptorW(securityDescriptor, 1, out nint pSD, out uint szSD))
|
||||
{
|
||||
Logger.LogError("Couldn't convert security descriptor string to security descriptor");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NativeMethods.SetServiceObjectSecurity(hService, 4, pSD))
|
||||
{
|
||||
Logger.LogError("Couldn't set MWB Service security descriptor");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.CloseServiceHandle(schSCManager);
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
}
|
||||
|
||||
private void UnregisterService()
|
||||
{
|
||||
IntPtr schSCManager = NativeMethods.OpenSCManagerW(string.Empty, "ServicesActive", NativeMethods.SCMANAGERALLACCESS);
|
||||
if (schSCManager == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open Service Control Manager");
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr hService = NativeMethods.OpenServiceW(schSCManager, "PowerToys.MWB.Service", 0x0020 | 0x10000);
|
||||
|
||||
if (hService == IntPtr.Zero)
|
||||
{
|
||||
Logger.LogError("Couldn't open MWB Service");
|
||||
return;
|
||||
}
|
||||
|
||||
NativeMethods.ServiceStatus status = default;
|
||||
if (NativeMethods.ControlService(hService, 0x0001, ref status))
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
while (NativeMethods.QueryServiceStatusW(hService, ref status))
|
||||
{
|
||||
if (status.dwCurrentState == 0x0003)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outer:
|
||||
bool deleteResult = NativeMethods.DeleteService(hService);
|
||||
NativeMethods.CloseServiceHandle(hService);
|
||||
|
||||
if (!deleteResult)
|
||||
{
|
||||
Logger.LogError("Couldn't delete MWB Service");
|
||||
}
|
||||
}
|
||||
|
||||
private void LaunchAddFirewallProcess()
|
||||
{
|
||||
string args = "/S /c \"" +
|
||||
"echo \"Deleting existing inbound firewall rules for PowerToys.MouseWithoutBorders.exe\"" +
|
||||
" & netsh advfirewall firewall delete rule dir=in name=all program=\"" +
|
||||
"\\PowerToys.MouseWithoutBorders.exe" +
|
||||
"\" & echo \"Adding an inbound firewall rule for PowerToys.MouseWithoutBorders.exe\"" +
|
||||
" & netsh advfirewall firewall add rule name=\"PowerToys.MouseWithoutBorders\" dir=in action=allow program=\"" +
|
||||
"\\PowerToys.MouseWithoutBorders.exe" +
|
||||
"\" enable=yes remoteip=any profile=any protocol=tcp & pause\"";
|
||||
|
||||
new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
Arguments = args,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
Verb = "runas",
|
||||
FileName = "cmd.exe",
|
||||
},
|
||||
}.Start();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
var services = Process.GetProcessesByName("PowerToys.MouseWithoutBordersService");
|
||||
services = [..services, ..Process.GetProcessesByName("PowerToys.MouseWithoutBorders"), ..Process.GetProcessesByName("PowerToys.MouseWithoutBordersHelper")];
|
||||
|
||||
foreach (var service in services)
|
||||
{
|
||||
try
|
||||
{
|
||||
service.Kill();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to kill process.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
private bool _runInServiceMode;
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
var settings = SettingsUtils.Default.GetSettings<MouseWithoutBordersSettings>(Name).Properties;
|
||||
|
||||
bool newRunInServiceMode = settings.UseService && GPOWrapper.GetConfiguredMwbAllowServiceModeValue() != GpoRuleConfigured.Disabled;
|
||||
|
||||
if (newRunInServiceMode == _runInServiceMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_runInServiceMode = newRunInServiceMode;
|
||||
Disable();
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
if (_runInServiceMode)
|
||||
{
|
||||
RegisterService();
|
||||
}
|
||||
else
|
||||
{
|
||||
var processes = Process.GetProcessesByName("PowerToys.MouseWithoutBordersService");
|
||||
foreach (var p in processes)
|
||||
{
|
||||
bool stopped = false;
|
||||
do
|
||||
{
|
||||
stopped = p.HasExited;
|
||||
}
|
||||
while (!stopped);
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
LaunchProcess();
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class NewPlusModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "NewPlus";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.NewPlus;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredNewPlusEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateNewPlusRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateNewPlusRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "NewPlusPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.NewPlus.ShellExtension.dll")]
|
||||
private static partial void UpdateNewPlusRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class PeekModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
private static readonly nint PeekDllHandle = LoadPeekDll();
|
||||
|
||||
private static nint LoadPeekDll()
|
||||
{
|
||||
// Pin the DLL in memory for the life of the Runner process, because it owns WinEvent hook callbacks.
|
||||
var dllPath = Path.Combine(AppContext.BaseDirectory, "WinUI3Apps", "PowerToys.Peek.dll");
|
||||
return NativeLibrary.Load(dllPath);
|
||||
}
|
||||
|
||||
private readonly EventWaitHandle terminatePeekEvent = new(false, EventResetMode.AutoReset, Constants.TerminatePeekEvent());
|
||||
|
||||
public string Name => "Peek";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Peek;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPeekEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.Peek.UI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Peek.UI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
terminatePeekEvent.Set();
|
||||
PeekSetForegroundHookActive(false);
|
||||
PeekManageSpaceModeHook();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
terminatePeekEvent.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Todo: Implement always launch non-elevated
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<PeekSettings>(Name).Properties;
|
||||
HotkeySettings hotkey = settings.EnableSpaceToActivate.Value ? new HotkeySettings(false, false, false, false, 0x20) : settings.DefaultActivationShortcut;
|
||||
Shortcuts.Add((hotkey, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
|
||||
PeekOnHotkey();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
PeekSetForegroundHookActive(SettingsUtils.Default.GetSettings<PeekSettings>(Name).Properties.EnableSpaceToActivate.Value);
|
||||
PeekManageSpaceModeHook();
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool PeekOnHotkey();
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
private static partial void PeekSetForegroundHookActive([MarshalAs(UnmanagedType.Bool)] bool active);
|
||||
|
||||
[LibraryImport("WinUI3Apps\\PowerToys.Peek.dll")]
|
||||
private static partial void PeekManageSpaceModeHook();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerAccentModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "PowerAccent";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.PowerAccent;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredQuickAccentEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.PowerAccent.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerAccent";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerDisplayModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IDisposable
|
||||
{
|
||||
private EventWaitHandle _refreshMonitorsEvent = new(false, EventResetMode.AutoReset, Constants.RefreshPowerDisplayMonitorsEvent());
|
||||
|
||||
public string Name => "PowerDisplay";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerDisplay;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerDisplayEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.PowerDisplay.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerDisplay.exe";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
private static readonly string _outputPipeName = "powertoys_power_display_" + Guid.NewGuid();
|
||||
private readonly TwoWayPipeMessageIPCManaged _ipc = new("\\\\.\\pipe\\powertoys_power_display_input", "\\\\.\\pipe\\" + _outputPipeName, (_) => { });
|
||||
|
||||
public override string ProcessArguments => _outputPipeName;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_ipc.Send(Constants.PowerDisplayTerminateAppMessage());
|
||||
_ipc.End();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
_ipc.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ipc.Dispose();
|
||||
_refreshMonitorsEvent.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions => new()
|
||||
{
|
||||
{ "Launch", (_) => { _ipc.Send(Constants.PowerDisplayToggleMessage()); } },
|
||||
{ "RefreshMonitors", (_) => { _refreshMonitorsEvent.Set(); } },
|
||||
{ "ApplyProfile", (string profile) => { _ipc.Send(Constants.PowerDisplayApplyProfileMessage() + " " + profile); } },
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerOCRModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "TextExtractor";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerOcr;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredTextExtractorEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.PowerOCR.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerOCR";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<PowerOcrSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
using var invokeOcrEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent());
|
||||
invokeOcrEvent.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminatePowerOCRSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class PowerRenameModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "PowerRename";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerRename;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerRenameEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdatePowerRenameRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdatePowerRenameRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "PowerRenameContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.PowerRenameExt.dll")]
|
||||
private static partial void UpdatePowerRenameRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class PowerToysRunModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
public string Name => "PowerToys Run";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.PowerLauncher;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
|
||||
|
||||
public override string ProcessPath => Path.GetFullPath("PowerToys.PowerLauncher.exe");
|
||||
|
||||
public override string ProcessName => "PowerToys.PowerLauncher";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.ElevateIfApplicable | ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public override string ProcessArguments => $"-powerToysPid {Environment.ProcessId}";
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.RunExitEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts =>
|
||||
[
|
||||
(
|
||||
SettingsUtils.Default.GetSettings<PowerLauncherSettings>(Name).Properties.OpenPowerLauncher,
|
||||
() =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeRunEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.PowerLauncherCentralizedHookSharedEvent());
|
||||
invokeRunEvent.Set();
|
||||
}
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.Win32;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class RegistryPreviewModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.RegistryPreview;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
|
||||
|
||||
public string Name => "RegistryPreview";
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.RegistryPreview.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.RegistryPreview";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (!RegistryPreviewChangeSet.UnApplyIfApplied())
|
||||
{
|
||||
Logger.LogError("Unapplying registry changes failed");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
bool defaultRegApp = SettingsUtils.Default.GetSettings<RegistryPreviewSettings>(Name).Properties.DefaultRegApp;
|
||||
if (defaultRegApp && !RegistryPreviewSetDefaultAppChangeSet.IsApplied)
|
||||
{
|
||||
if (!RegistryPreviewSetDefaultAppChangeSet.Apply())
|
||||
{
|
||||
Logger.LogError("Applying reg default handler failed.");
|
||||
}
|
||||
|
||||
NativeMethods.SHChangeNotify(NativeMethods.SHCNE_ASSOCCHANGED, NativeMethods.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
else if (!defaultRegApp && RegistryPreviewSetDefaultAppChangeSet.IsApplied)
|
||||
{
|
||||
if (RegistryPreviewSetDefaultAppChangeSet.UnApply())
|
||||
{
|
||||
Logger.LogError("Unapplying reg default handler failed.");
|
||||
}
|
||||
|
||||
NativeMethods.SHChangeNotify(NativeMethods.SHCNE_ASSOCCHANGED, NativeMethods.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
if (!RegistryPreviewChangeSet.ApplyIfNotApplied())
|
||||
{
|
||||
Logger.LogError("Applying registry changes failed");
|
||||
}
|
||||
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions
|
||||
{
|
||||
get => new() { { "Launch", (_) => LaunchProcess() } };
|
||||
}
|
||||
|
||||
private RegistryChangeSet RegistryPreviewSetDefaultAppChangeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
string installationDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
string appName = "Registry Preview";
|
||||
string registryKeyPrefix = "Software\\Classes\\";
|
||||
RegistryValueChange[] changes =
|
||||
[
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\Application",
|
||||
KeyName = "ApplicationName",
|
||||
Value = appName,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\DefaultIcon",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ProcessName + "\\shell\\open\\command",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe \"----ms-protocol:ms-encodedlaunch:App?ContractId=Windows.File&Verb=open&File=%1\"",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = registryKeyPrefix + ".reg\\OpenWithProgIDs",
|
||||
KeyName = null,
|
||||
Value = ProcessName,
|
||||
}
|
||||
];
|
||||
return new RegistryChangeSet { Changes = changes };
|
||||
}
|
||||
}
|
||||
|
||||
private RegistryChangeSet RegistryPreviewChangeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
string installationDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
RegistryValueChange[] changes =
|
||||
[
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = "Software\\Classes\\regfile\\shell\\preview\\command",
|
||||
KeyName = null,
|
||||
Value = installationDir + "\\WinUI3Apps\\PowerToys.RegistryPreview.exe \"%1\"",
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = "Software\\Classes\\regfile\\shell\\preview",
|
||||
KeyName = "icon",
|
||||
Value = installationDir + "\\WinUI3Apps\\Assets\\RegistryPreview\\RegistryPreview.ico",
|
||||
}
|
||||
];
|
||||
return new RegistryChangeSet() { Changes = changes };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ShortcutGuideModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Shortcut Guide";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ShortcutGuide;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredShortcutGuideEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.ShortcutGuide.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ShortcutGuide";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SupressLaunchOnModuleEnabled;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<ShortcutGuideSettings>(Name).Properties.OpenShortcutGuide, () =>
|
||||
{
|
||||
if (Process.GetProcessesByName(ProcessName).Length == 0)
|
||||
{
|
||||
LaunchProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessExit();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class WorkspacesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Workspaces";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Workspaces;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredWorkspacesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.WorkspacesEditor.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.WorkspacesEditor";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<WorkspacesSettings>(Name).Properties.Hotkey, () =>
|
||||
{
|
||||
LaunchProcess();
|
||||
}));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ZoomItModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "ZoomIt";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ZoomIt;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredZoomItEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.ZoomIt.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ZoomIt";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions { get => new() { { "refresh_settings", (_) => OnSettingsChanged() } }; }
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
using var refreshSettingsEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ZoomItRefreshSettingsEvent());
|
||||
refreshSettingsEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
346
src/RunnerV2/RunnerV2/NativeMethods.cs
Normal file
346
src/RunnerV2/RunnerV2/NativeMethods.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Windows.ApplicationModel;
|
||||
|
||||
namespace RunnerV2
|
||||
{
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
[LibraryImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
|
||||
|
||||
[LibraryImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, ref TokenElevation tokenInformation, uint tokenInformationLength, out uint returnLength);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool CloseHandle(IntPtr hObject);
|
||||
|
||||
internal enum TOKEN_INFORMATION_CLASS
|
||||
{
|
||||
TOKEN_ELEVATION = 20,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct TokenElevation
|
||||
{
|
||||
public uint TokenIsElevated;
|
||||
}
|
||||
|
||||
internal const int TOKENQUERY = 0x0008;
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool AppendMenuW(IntPtr hMenu, uint uFlags, UIntPtr uIDNewItem, string lpNewItem);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial IntPtr CreatePopupMenu();
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr FindWindowW(string lpClassName, string lpWindowName);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
|
||||
|
||||
internal const uint NIMADD = 0x00000000;
|
||||
internal const uint NIMDELETE = 0x00000002;
|
||||
|
||||
internal struct NOTIFYICONDATA
|
||||
{
|
||||
public uint CbSize;
|
||||
public IntPtr HWnd;
|
||||
public uint UId;
|
||||
public uint UFlags;
|
||||
public uint UCallbackMessage;
|
||||
public IntPtr HIcon;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string SzTip;
|
||||
public uint DwState;
|
||||
public uint DwStateMask;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string SzInfo;
|
||||
public uint UTimeoutOrVersion;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string SzInfoTitle;
|
||||
public uint DwInfoFlags;
|
||||
public Guid GuidItem;
|
||||
public IntPtr HBalloonIcon;
|
||||
}
|
||||
|
||||
[DllImport("shell32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool Shell_NotifyIcon(uint dwMessage, ref NOTIFYICONDATA lpdata);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, uint action, IntPtr pChangeFilterStruct);
|
||||
|
||||
internal const uint CSVREDRAW = 0x0001;
|
||||
internal const uint CSHREDRAW = 0x0002;
|
||||
|
||||
internal const uint WSOVERLAPPEDWINDOW = 0x00CF0000;
|
||||
internal const uint WSPOPUP = 0x80000000;
|
||||
|
||||
internal const int CWUSEDEFAULT = unchecked((int)0x80000000);
|
||||
|
||||
internal static readonly IntPtr IDCARROW = new(32512);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern IntPtr GetMessageW(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool TranslateMessage(ref MSG lpMsg);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DispatchMessageW(ref MSG lpMsg);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool PostMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
internal static partial ushort AddAtomW([MarshalAs(UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
internal struct MSG
|
||||
{
|
||||
public IntPtr HWnd;
|
||||
public uint Message;
|
||||
public UIntPtr WParam;
|
||||
public long LParam;
|
||||
public ulong Time;
|
||||
public Point Pt;
|
||||
}
|
||||
|
||||
internal enum WindowMessages : uint
|
||||
{
|
||||
COMMAND = 0x0111,
|
||||
HOTKEY = 0x0312,
|
||||
ICON_NOTIFY = 0x0800,
|
||||
WINDOWPOSCHANGING = 0x0046,
|
||||
DESTROY = 0x0002,
|
||||
REFRESH_SETTINGS = 0x0400 + 2,
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern ushort RegisterClassW(ref WNDCLASS lpWndClass);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = false)]
|
||||
internal static partial IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial uint RegisterWindowMessageW([MarshalAs(UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial nint CreateWindowExW(
|
||||
uint dwExStyle,
|
||||
string lpClassName,
|
||||
string lpWindowName,
|
||||
uint dwStyle,
|
||||
int x,
|
||||
int y,
|
||||
int nWidth,
|
||||
int nHeight,
|
||||
IntPtr hWndParent,
|
||||
IntPtr hMenu,
|
||||
IntPtr hInstance,
|
||||
IntPtr lpParam);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct WNDCLASS
|
||||
{
|
||||
public uint Style;
|
||||
public WndProc LpfnWndProc;
|
||||
public int CbClsExtra;
|
||||
public int CbWndExtra;
|
||||
public IntPtr HInstance;
|
||||
public IntPtr HIcon;
|
||||
public IntPtr HCursor;
|
||||
public IntPtr HbrBackground;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string LpszMenuName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string LpszClassName;
|
||||
}
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string StringSecurityDescriptor,
|
||||
uint StringSDRevision,
|
||||
out IntPtr SecurityDescriptor,
|
||||
out uint SecurityDescriptorSize);
|
||||
|
||||
[DllImport("Advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool MakeAbsoluteSD(
|
||||
IntPtr pSelfRelativeSD,
|
||||
IntPtr pAbsoluteSD,
|
||||
ref uint lpdwAbsoluteSDSize,
|
||||
IntPtr pDacl,
|
||||
ref uint lpdwDaclSize,
|
||||
IntPtr pSacl,
|
||||
ref uint lpdwSaclSize,
|
||||
IntPtr pOwner,
|
||||
ref uint lpdwOwnerSize,
|
||||
IntPtr pPrimaryGroup,
|
||||
ref uint lpdwPrimaryGroupSize);
|
||||
|
||||
[DllImport("ole32.dll", SetLastError = true)]
|
||||
internal static extern int CoInitializeSecurity(
|
||||
IntPtr pSecDesc,
|
||||
int cAuthSvc,
|
||||
IntPtr asAuthSvc,
|
||||
IntPtr pReserved1,
|
||||
uint dwAuthnLevel,
|
||||
uint dwImpLevel,
|
||||
IntPtr pAuthList,
|
||||
uint dwCapabilities,
|
||||
IntPtr pReserved3);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize);
|
||||
|
||||
[LibraryImport("Shell32.dll", SetLastError = true)]
|
||||
internal static partial void SHChangeNotify(
|
||||
uint wEventId,
|
||||
uint uFlags,
|
||||
IntPtr dwItem1,
|
||||
IntPtr dwItem2);
|
||||
|
||||
internal const uint SHCNE_ASSOCCHANGED = 0x8000000;
|
||||
internal const uint SHCNF_IDLIST = 0x0;
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr OpenSCManagerW(string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr OpenServiceW(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool ControlService(IntPtr hService, uint dwControl, ref ServiceStatus lpServiceStatus);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool CloseServiceHandle(IntPtr hSCObject);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool StartServiceW(IntPtr hService, uint dwNumServiceArgs, IntPtr lpServiceArgVectors);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool QueryServiceStatusW(IntPtr hService, ref ServiceStatus lpServiceStatus);
|
||||
|
||||
[LibraryImport("Advapi32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool DeleteService(IntPtr hService);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool QueryServiceConfigW(IntPtr hService, IntPtr lpServiceConfig, uint cbBufSize, out uint pcbBytesNeeded);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool ChangeServiceConfigW(
|
||||
IntPtr hService,
|
||||
uint dwServiceType,
|
||||
uint dwStartType,
|
||||
uint dwErrorControl,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup,
|
||||
IntPtr lpdwTagId,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDependencies,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpPassword,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool SetServiceObjectSecurity(
|
||||
IntPtr hService,
|
||||
uint dwSecurityInformation,
|
||||
IntPtr pSecurityDescriptor);
|
||||
|
||||
[DllImport("Advapi32.dll")]
|
||||
internal static extern IntPtr CreateServiceW(
|
||||
IntPtr hSCManager,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDisplayName,
|
||||
uint dwDesiredAccess,
|
||||
uint dwServiceType,
|
||||
uint dwStartType,
|
||||
uint dwErrorControl,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpBinaryPathName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpLoadOrderGroup,
|
||||
IntPtr lpdwTagId,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpDependencies,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpServiceStartName,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string lpPassword);
|
||||
|
||||
internal const uint SCMANAGERALLACCESS = 0x000F0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020;
|
||||
|
||||
internal const uint SERVICEALLACCESS = 0x000F0000 | 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ServiceStatus
|
||||
{
|
||||
public uint dwServiceType;
|
||||
public uint dwCurrentState;
|
||||
public uint dwControlsAccepted;
|
||||
public uint dwWin32ExitCode;
|
||||
public uint dwServiceSpecificExitCode;
|
||||
public uint dwCheckPoint;
|
||||
public uint dwWaitHint;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct QueryServiceConfig
|
||||
{
|
||||
public uint dwServiceType;
|
||||
public uint dwStartType;
|
||||
public uint dwErrorControl;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpBinaryPathName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpLoadOrderGroup;
|
||||
public uint dwTagId;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpDependencies;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpServiceStartName;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string lpDisplayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
173
src/RunnerV2/RunnerV2/Program.cs
Normal file
173
src/RunnerV2/RunnerV2/Program.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.Win32;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
using Settings.UI.Library;
|
||||
|
||||
internal sealed class Program
|
||||
{
|
||||
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
|
||||
|
||||
internal static GeneralSettings GeneralSettings => _settingsUtils.GetSettings<GeneralSettings>();
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
string securityDescriptor =
|
||||
"O:BA" // Owner: Builtin (local) administrator
|
||||
+ "G:BA" // Group: Builtin (local) administrator
|
||||
+ "D:"
|
||||
+ "(A;;0x7;;;PS)" // Access allowed on COM_RIGHTS_EXECUTE, _LOCAL, & _REMOTE for Personal self
|
||||
+ "(A;;0x7;;;IU)" // Access allowed on COM_RIGHTS_EXECUTE for Interactive Users
|
||||
+ "(A;;0x3;;;SY)" // Access allowed on COM_RIGHTS_EXECUTE, & _LOCAL for Local system
|
||||
+ "(A;;0x7;;;BA)" // Access allowed on COM_RIGHTS_EXECUTE, _LOCAL, & _REMOTE for Builtin (local) administrator
|
||||
+ "(A;;0x3;;;S-1-15-3-1310292540-1029022339-4008023048-2190398717-53961996-4257829345-603366646)" // Access allowed on COM_RIGHTS_EXECUTE, & _LOCAL for Win32WebViewHost package capability
|
||||
+ "S:"
|
||||
+ "(ML;;NX;;;LW)"; // Integrity label on No execute up for Low mandatory level
|
||||
|
||||
COMUtils.InitializeCOMSecurity(securityDescriptor);
|
||||
|
||||
switch (ShouldRunInSpecialMode(args))
|
||||
{
|
||||
case SpecialMode.None:
|
||||
break;
|
||||
case SpecialMode.UpdateNow:
|
||||
UpdateNow();
|
||||
return;
|
||||
case SpecialMode.DisableCantDragElevatedNotification:
|
||||
Environment.Exit(NotificationHelper.DisableToast(NotificationHelper.ToastType.ElevatedDontShowAgain) ? 1 : 0);
|
||||
return;
|
||||
case SpecialMode.CouldntToggleFileExplorerModulesNotification:
|
||||
Environment.Exit(NotificationHelper.DisableToast(NotificationHelper.ToastType.CouldntToggleFileExplorerModules) ? 1 : 0);
|
||||
return;
|
||||
default:
|
||||
throw new NotImplementedException("Special modes are not implemented yet.");
|
||||
}
|
||||
|
||||
bool shouldOpenSettings = args.Any(s => s.StartsWith("--open-settings", StringComparison.InvariantCulture));
|
||||
bool shouldOpenSettingsToSpecificPage = args.Any(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture));
|
||||
|
||||
// Check if PowerToys is already running
|
||||
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
|
||||
{
|
||||
IntPtr hwndMain = NativeMethods.FindWindowW(Runner.TrayWindowClassName, null!);
|
||||
NativeMethods.PostMessageW(hwndMain, 0x0111, 1, IntPtr.Zero);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GPOWrapper.GetAllowDataDiagnosticsValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Registry.CurrentUser.OpenSubKey("Software\\Classes\\PowerToys", true)?.SetValue("AllowDataDiagnostics", 0, RegistryValueKind.DWord);
|
||||
}
|
||||
|
||||
bool isElevated = ElevationHelper.IsProcessElevated();
|
||||
bool hasDontElevateArgument = args.Contains("--dont-elevate");
|
||||
bool runElevatedSetting = GeneralSettings.RunElevated;
|
||||
bool hasRestartedElevatedArgment = args.Contains("--restartedElevated");
|
||||
|
||||
Action afterInitializationAction = () => { };
|
||||
Version version = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
|
||||
if ($"v{version.Major}.{version.Minor}.{version.Build}" != _settingsUtils.GetSettings<LastVersionRunSettings>(fileName: "last_version_run.json").LastVersion && (!GeneralSettings.ShowWhatsNewAfterUpdates || GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() != GpoRuleConfigured.Disabled))
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
Logger.LogInfo("Open SCOOBE window because the version differs from the last run version");
|
||||
SettingsHelper.OpenSettingsWindow(showScoobeWindow: true);
|
||||
};
|
||||
}
|
||||
|
||||
if (!_settingsUtils.GetSettings<OOBESettings>(fileName: "oobe_settings.json").OpenedAtFirstLaunch)
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
Logger.LogInfo("Open OOBE window because it is the first launch");
|
||||
SettingsHelper.OpenSettingsWindow(showOobeWindow: true);
|
||||
};
|
||||
}
|
||||
|
||||
if (shouldOpenSettings)
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
SettingsHelper.OpenSettingsWindow(additionalArguments: shouldOpenSettingsToSpecificPage ? args.First(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture)).Replace("--open-settings=", string.Empty, StringComparison.InvariantCulture) : null);
|
||||
};
|
||||
}
|
||||
|
||||
// Set last version run
|
||||
_settingsUtils.SaveSettings(new LastVersionRunSettings() { LastVersion = $"v{version.Major}.{version.Minor}.{version.Build}" }.ToJsonString(), fileName: "last_version_run.json");
|
||||
|
||||
switch ((isElevated, hasDontElevateArgument, runElevatedSetting, hasRestartedElevatedArgment))
|
||||
{
|
||||
case (true, true, false, _):
|
||||
// Todo: Scheudle restart as non elevated
|
||||
throw new NotImplementedException();
|
||||
case (true, _, _, _):
|
||||
case (_, _, false, _):
|
||||
case (_, true, _, _):
|
||||
case (false, _, _, true):
|
||||
GeneralSettings tempGeneralSettings = GeneralSettings;
|
||||
tempGeneralSettings.IsElevated = isElevated;
|
||||
_settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString());
|
||||
|
||||
Runner.Run(afterInitializationAction);
|
||||
break;
|
||||
default:
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated;
|
||||
break;
|
||||
}
|
||||
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the application should run in a special mode based on the provided arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments passed to <see cref="Main(string[])"/></param>
|
||||
/// <returns>The <see cref="SpecialMode"/> the app should run in.</returns>
|
||||
private static SpecialMode ShouldRunInSpecialMode(string[] args)
|
||||
{
|
||||
if (args.Length > 0 && args[0].StartsWith("powertoys://", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
Uri uri = new(args[0]);
|
||||
string host = uri.Host.ToLowerInvariant();
|
||||
return host switch
|
||||
{
|
||||
"update_now" => SpecialMode.UpdateNow,
|
||||
"cant_drag_elevated_disable" => SpecialMode.DisableCantDragElevatedNotification,
|
||||
"couldnt_toggle_powerpreview_modules_disable" => SpecialMode.CouldntToggleFileExplorerModulesNotification,
|
||||
_ => SpecialMode.None,
|
||||
};
|
||||
}
|
||||
|
||||
return SpecialMode.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the update process for PowerToys.
|
||||
/// </summary>
|
||||
private static void UpdateNow()
|
||||
{
|
||||
Logger.LogInfo("Starting update process for PowerToys.");
|
||||
|
||||
Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
FileName = "PowerToys.Update.exe",
|
||||
Arguments = "-update_now",
|
||||
});
|
||||
}
|
||||
}
|
||||
369
src/RunnerV2/RunnerV2/Runner.cs
Normal file
369
src/RunnerV2/RunnerV2/Runner.cs
Normal file
@@ -0,0 +1,369 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
using RunnerV2.ModuleInterfaces;
|
||||
using Update;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2
|
||||
{
|
||||
internal static partial class Runner
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the window handle for the Runner main window that hosts the tray icon and receives system messages.
|
||||
/// </summary>
|
||||
public static nint RunnerHwnd { get; private set; }
|
||||
|
||||
public const string TrayWindowClassName = "pt_tray_icon_window_class";
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the currently loaded modules.
|
||||
/// </summary>
|
||||
public static List<IPowerToysModule> LoadedModules { get; } = [];
|
||||
|
||||
private static List<IPowerToysModule> _failedModuleLoads = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all available PowerToys modules.
|
||||
/// </summary>
|
||||
public static FrozenSet<IPowerToysModule> ModulesToLoad { get; } =
|
||||
[
|
||||
new ColorPickerModuleInterface(),
|
||||
new AlwaysOnTopModuleInterface(),
|
||||
new HostsModuleInterface(),
|
||||
new PowerAccentModuleInterface(),
|
||||
new AdvancedPasteModuleInterface(),
|
||||
new AwakeModuleInterface(),
|
||||
new CmdNotFoundModuleInterface(),
|
||||
new CommandPaletteModuleInterface(),
|
||||
new CropAndLockModuleInterface(),
|
||||
new EnvironmentVariablesModuleInterface(),
|
||||
new RegistryPreviewModuleInterface(),
|
||||
new FileExplorerModuleInterface(),
|
||||
new ZoomItModuleInterface(),
|
||||
new PowerOCRModuleInterface(),
|
||||
new MeasureToolModuleInterface(),
|
||||
new MouseJumpModuleInterface(),
|
||||
new FancyZonesModuleInterface(),
|
||||
new PowerToysRunModuleInterface(),
|
||||
new KeyboardManagerModuleInterface(),
|
||||
new LightSwitchModuleInterface(),
|
||||
new CursorWrapModuleInterface(),
|
||||
new FindMyMouseModuleInterface(),
|
||||
new WorkspacesModuleInterface(),
|
||||
new MousePointerCrosshairsModuleInterface(),
|
||||
new MouseHighlighterModuleInterface(),
|
||||
new MouseWithoutBordersModuleInterface(),
|
||||
new NewPlusModuleInterface(),
|
||||
new PowerRenameModuleInterface(),
|
||||
new ImageResizerModuleInterface(),
|
||||
new FileLocksmithModuleInterface(),
|
||||
new ShortcutGuideModuleInterface(),
|
||||
new PeekModuleInterface(),
|
||||
new PowerDisplayModuleInterface(),
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Runs the main message loop for Runner.
|
||||
/// </summary>
|
||||
/// <param name="afterInitializationAction">A function to execute after initialization.</param>
|
||||
internal static void Run(Action afterInitializationAction)
|
||||
{
|
||||
Logger.LogInfo("Runner started");
|
||||
|
||||
InitializeTrayWindow();
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
QuickAccessHelper.Start();
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook("QuickAccess", SettingsUtils.Default.GetSettings<GeneralSettings>().QuickAccessShortcut, QuickAccessHelper.Show);
|
||||
}
|
||||
|
||||
Task.Run(UpdateUtilities.UninstallPreviousMsixVersions);
|
||||
|
||||
foreach (IPowerToysModule module in ModulesToLoad)
|
||||
{
|
||||
ToggleModuleStateBasedOnEnabledProperty(module);
|
||||
}
|
||||
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
CentralizedKeyboardHookManager.Start();
|
||||
|
||||
afterInitializationAction();
|
||||
|
||||
MessageLoop();
|
||||
}
|
||||
|
||||
private static readonly uint _taskbarCreatedMessage = RegisterWindowMessageW("TaskbarCreated");
|
||||
|
||||
/// <summary>
|
||||
/// The main message loop that processes Windows messages.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void MessageLoop()
|
||||
{
|
||||
while (GetMessageW(out MSG msg, IntPtr.Zero, 0, 0) != 0 || true)
|
||||
{
|
||||
TranslateMessage(ref msg);
|
||||
DispatchMessageW(ref msg);
|
||||
|
||||
// Supress duplicate handling of HOTKEY messages
|
||||
if (msg.Message == (uint)WindowMessages.HOTKEY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HandleMessage(msg.HWnd, msg.Message, (nint)msg.WParam, (nint)msg.LParam);
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes Runner and all loaded modules.
|
||||
/// </summary>
|
||||
[DoesNotReturn]
|
||||
internal static void Close()
|
||||
{
|
||||
TrayIconManager.StopTrayIcon();
|
||||
SettingsHelper.CloseSettingsWindow();
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
QuickAccessHelper.Stop();
|
||||
|
||||
foreach (IPowerToysModule module in LoadedModules)
|
||||
{
|
||||
try
|
||||
{
|
||||
module.Disable();
|
||||
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.ProcessExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the state of a module based on its enabled property and GPO rules.
|
||||
/// </summary>
|
||||
/// <param name="module">The module to toggle</param>
|
||||
public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + module.Name + "\\ModuleInterface\\Logs");
|
||||
if (_failedModuleLoads.Contains(module))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ((module.Enabled && (module.GpoRuleConfigured != PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)) || module.GpoRuleConfigured == PowerToys.GPOWrapper.GpoRuleConfigured.Enabled)
|
||||
{
|
||||
/* Todo: conflict manager */
|
||||
|
||||
if (!LoadedModules.Contains(module))
|
||||
{
|
||||
module.Enable();
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.LaunchProcess(true);
|
||||
}
|
||||
|
||||
LoadedModules.Add(module);
|
||||
}
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule(module.Name);
|
||||
|
||||
if (module is IPowerToysModuleShortcutsProvider shortcutsProvider)
|
||||
{
|
||||
foreach (var shortcut in shortcutsProvider.Shortcuts.ToArray())
|
||||
{
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook(module.Name, shortcut.Hotkey, shortcut.Action);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if RELEASE
|
||||
MessageBox.Show($"The module {module.Name} failed to load: \n" + e.Message, "Error: " + e.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
#endif
|
||||
Logger.LogError($"The module {module.Name} failed to load: \n", e);
|
||||
_failedModuleLoads.Add(module);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
module.Disable();
|
||||
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
pmac.ProcessExit();
|
||||
}
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule(module.Name);
|
||||
|
||||
LoadedModules.Remove(module);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if RELEASE
|
||||
MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error: " + e.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
#endif
|
||||
Logger.LogError($"The module {module.Name} failed to unload: \n", e);
|
||||
_failedModuleLoads.Add(module);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the tray window to receive system messages.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void InitializeTrayWindow()
|
||||
{
|
||||
IntPtr hInstance = Process.GetCurrentProcess().MainModule!.BaseAddress;
|
||||
IntPtr hCursor = Cursors.Arrow.Handle;
|
||||
IntPtr hIcon = SystemIcons.Application.Handle;
|
||||
|
||||
var wc = new WNDCLASS
|
||||
{
|
||||
HCursor = hCursor,
|
||||
HInstance = hInstance,
|
||||
LpszClassName = TrayWindowClassName,
|
||||
Style = CSHREDRAW | CSVREDRAW,
|
||||
LpfnWndProc = HandleMessage,
|
||||
HIcon = hIcon,
|
||||
HbrBackground = IntPtr.Zero,
|
||||
LpszMenuName = string.Empty,
|
||||
CbClsExtra = 0,
|
||||
CbWndExtra = 0,
|
||||
};
|
||||
|
||||
_ = RegisterClassW(ref wc);
|
||||
|
||||
RunnerHwnd = CreateWindowExW(
|
||||
0,
|
||||
wc.LpszClassName,
|
||||
TrayWindowClassName,
|
||||
WSOVERLAPPEDWINDOW | WSPOPUP,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
CWUSEDEFAULT,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
wc.HInstance,
|
||||
IntPtr.Zero);
|
||||
|
||||
if (RunnerHwnd == IntPtr.Zero)
|
||||
{
|
||||
var err = Marshal.GetLastPInvokeError();
|
||||
MessageBox.Show($"CreateWindowExW failed. LastError={err}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles Windows messages sent to the tray window.
|
||||
/// </summary>
|
||||
private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case (uint)WindowMessages.ICON_NOTIFY:
|
||||
TrayIconManager.ProcessTrayIconMessage(lParam);
|
||||
break;
|
||||
case (uint)WindowMessages.COMMAND:
|
||||
TrayIconManager.ProcessTrayMenuCommand((nuint)wParam);
|
||||
break;
|
||||
case (uint)WindowMessages.WINDOWPOSCHANGING:
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
case (uint)WindowMessages.DESTROY:
|
||||
Close();
|
||||
break;
|
||||
case (uint)WindowMessages.REFRESH_SETTINGS:
|
||||
foreach (IPowerToysModule module in ModulesToLoad)
|
||||
{
|
||||
ToggleModuleStateBasedOnEnabledProperty(module);
|
||||
}
|
||||
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule("QuickAccess");
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
CentralizedKeyboardHookManager.AddKeyboardHook("QuickAccess", SettingsUtils.Default.GetSettings<GeneralSettings>().QuickAccessShortcut, QuickAccessHelper.Show);
|
||||
}
|
||||
else
|
||||
{
|
||||
CentralizedKeyboardHookManager.RemoveAllHooksFromModule("QuickAccess");
|
||||
QuickAccessHelper.Stop();
|
||||
}
|
||||
|
||||
TrayIconManager.UpdateTrayIcon();
|
||||
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
else
|
||||
{
|
||||
TrayIconManager.StopTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if (msg == _taskbarCreatedMessage && SettingsUtils.Default.GetSettings<GeneralSettings>().ShowSysTrayIcon)
|
||||
{
|
||||
TrayIconManager.StartTrayIcon();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/RunnerV2/RunnerV2/RunnerV2.csproj
Normal file
33
src/RunnerV2/RunnerV2/RunnerV2.csproj
Normal file
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\Common.SelfContained.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Description>PowerToys Runner</Description>
|
||||
<AssemblyName>PowerToys</AssemblyName>
|
||||
<OutputPath>..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\GPOWrapperProjection\GPOWrapperProjection.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedCsWin32\ManagedCsWin32.csproj" />
|
||||
<ProjectReference Include="..\..\modules\poweraccent\PowerAccent.UI\PowerAccent.UI.csproj" />
|
||||
<ProjectReference Include="..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\..\Update\Update.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\PowerToysDark.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\PowerToysLight.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
18
src/RunnerV2/RunnerV2/app.manifest
Normal file
18
src/RunnerV2/RunnerV2/app.manifest
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
BIN
src/RunnerV2/RunnerV2/icon.ico
Normal file
BIN
src/RunnerV2/RunnerV2/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
@@ -1,36 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../common/version/version.h"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
@@ -1,234 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
#include <common/updating/updating.h>
|
||||
#include <common/updating/updateState.h>
|
||||
#include <common/updating/installer.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/HttpClient.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
#include <Msi.h>
|
||||
|
||||
#include "../runner/tray_icon.h"
|
||||
#include "../runner/UpdateUtils.h"
|
||||
|
||||
using namespace cmdArg;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::optional<fs::path> CopySelfToTempDir()
|
||||
{
|
||||
std::error_code error;
|
||||
auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe";
|
||||
fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error);
|
||||
if (error)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::move(dst_path);
|
||||
}
|
||||
|
||||
std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
{
|
||||
using namespace updating;
|
||||
|
||||
isUpToDate = false;
|
||||
|
||||
auto state = UpdateState::read();
|
||||
|
||||
const auto new_version_info = get_github_version_info_async().get();
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = download_new_version(std::get<new_version_download_info>(*new_version_info)).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
else if (state.state == UpdateState::readyToInstall)
|
||||
{
|
||||
fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename };
|
||||
if (fs::is_regular_file(installer))
|
||||
{
|
||||
return std::move(installer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"Couldn't find a downloaded installer {}", installer.native());
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else if (state.state == UpdateState::upToDate)
|
||||
{
|
||||
isUpToDate = true;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Logger::error("Invoked with -update_now argument, but update state was invalid");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool InstallNewVersionStage1(fs::path installer)
|
||||
{
|
||||
if (auto copy_in_temp = CopySelfToTempDir())
|
||||
{
|
||||
// Detect if PT was running
|
||||
const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr);
|
||||
|
||||
if (pt_main_window != nullptr)
|
||||
{
|
||||
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
|
||||
arguments += L" \"";
|
||||
arguments += installer.c_str();
|
||||
arguments += L"\"";
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = copy_in_temp->c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
|
||||
sei.lpParameters = arguments.c_str();
|
||||
return ShellExecuteExW(&sei) == TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool InstallNewVersionStage2(std::wstring installer_path)
|
||||
{
|
||||
std::transform(begin(installer_path), end(installer_path), begin(installer_path), ::towlower);
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (installer_path.ends_with(L".msi"))
|
||||
{
|
||||
success = MsiInstallProductW(installer_path.data(), nullptr) == ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's not .msi, then it's a wix bootstrapper
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE };
|
||||
sei.lpFile = installer_path.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
std::wstring parameters = L"/passive /norestart";
|
||||
sei.lpParameters = parameters.c_str();
|
||||
|
||||
success = ShellExecuteExW(&sei) == TRUE;
|
||||
|
||||
// Wait for the install completion
|
||||
if (success)
|
||||
{
|
||||
WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(sei.hProcess, &exitCode);
|
||||
success = exitCode == 0;
|
||||
CloseHandle(sei.hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = UpdateState::upToDate;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
int nArgs = 0;
|
||||
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
||||
if (!args || nArgs < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring_view action{ args[1] };
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
|
||||
logFilePath.append(LogSettings::updateLogPath);
|
||||
Logger::init(LogSettings::updateLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
|
||||
if (action == UPDATE_NOW_LAUNCH_STAGE1)
|
||||
{
|
||||
bool isUpToDate = false;
|
||||
auto installerPath = ObtainInstaller(isUpToDate);
|
||||
bool failed = !installerPath.has_value();
|
||||
failed = failed || !InstallNewVersionStage1(std::move(*installerPath));
|
||||
if (failed)
|
||||
{
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = isUpToDate ? UpdateState::upToDate : UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
const bool failed = !InstallNewVersionStage2(args[2]);
|
||||
if (failed)
|
||||
{
|
||||
UpdateState::store([&](UpdateState& state) {
|
||||
state = {};
|
||||
state.githubUpdateLastCheckedDate.emplace(timeutil::now());
|
||||
state.state = UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h PowerToys.Update.base.rc PowerToys.Update.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}</ProjectGuid>
|
||||
<RootNamespace>Update</RootNamespace>
|
||||
<ProjectName>PowerToys.Update</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\deps\expected.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup>
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WindowsApp.lib;Msi.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="PowerToys.Update.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\notifications\notifications.vcxproj">
|
||||
<Project>{1d5be09d-78c0-4fd7-af00-ae7c1af7c525}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\updating\updating.vcxproj">
|
||||
<Project>{17da04df-e393-4397-9cf0-84dabe11032e}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PowerToys.Update.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\PowerToys.Update.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
183
src/Update/Program.cs
Normal file
183
src/Update/Program.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading.Tasks;
|
||||
using Update;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
internal sealed partial class Program
|
||||
{
|
||||
private static readonly string _installerPath = Path.Combine(Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Microsoft",
|
||||
"PowerToys",
|
||||
"Updates"));
|
||||
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
string action = args[0];
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case UpdateStage.UPDATENOWLAUNCHSTAGE1:
|
||||
await PerformUpdateNowStage1();
|
||||
break;
|
||||
case UpdateStage.UPDATENOWLAUNCHSTAGE2:
|
||||
if (args.Length < 2)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
await PerformUpdateNowStage2(args[1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task PerformUpdateNowStage2(string installerPath)
|
||||
{
|
||||
Process installerProcess = new()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = installerPath,
|
||||
Arguments = "/passive /norestart",
|
||||
UseShellExecute = true,
|
||||
},
|
||||
};
|
||||
|
||||
installerProcess.Start();
|
||||
await installerProcess.WaitForExitAsync();
|
||||
|
||||
if (installerProcess.ExitCode == 0)
|
||||
{
|
||||
UpdateSettingsHelper.ProcessNoUpdateAvailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSettingsHelper.SetUpdateState(UpdatingSettings.UpdatingState.ErrorDownloading);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task PerformUpdateNowStage1()
|
||||
{
|
||||
UpdateSettingsHelper.TriggerUpdateCheck();
|
||||
UpdateSettingsHelper.UpdateInfo updateInfo = await UpdateSettingsHelper.GetUpdateAvailableInfo();
|
||||
|
||||
if (updateInfo is not UpdateSettingsHelper.UpdateInfo.UpdateAvailable ua)
|
||||
{
|
||||
// No update found
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy itsself to the temp folder
|
||||
File.Copy("PowerToys.Update.exe", Path.Combine(Path.GetTempPath(), "PowerToys.Update.exe"), true);
|
||||
|
||||
string? installerFilePath = null;
|
||||
|
||||
switch (UpdateSettingsHelper.GetUpdateState())
|
||||
{
|
||||
case UpdatingSettings.UpdatingState.ReadyToDownload:
|
||||
case UpdatingSettings.UpdatingState.ErrorDownloading:
|
||||
CleanupUpdates();
|
||||
installerFilePath = await DownloadFile(ua.InstallerDownloadUrl.ToString(), ua.InstallerFilename);
|
||||
break;
|
||||
case UpdatingSettings.UpdatingState.ReadyToInstall:
|
||||
installerFilePath = Path.Combine(_installerPath, ua.InstallerFilename);
|
||||
if (!File.Exists(installerFilePath))
|
||||
{
|
||||
// Installer not found
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case UpdatingSettings.UpdatingState.UpToDate:
|
||||
Environment.Exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (installerFilePath == null)
|
||||
{
|
||||
UpdateSettingsHelper.SetUpdateState(UpdatingSettings.UpdatingState.ErrorDownloading);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr runnerHwnd = FindWindowW("pt_tray_icon_window_class");
|
||||
|
||||
if (runnerHwnd != IntPtr.Zero)
|
||||
{
|
||||
SendMessageW(runnerHwnd, 0x0010, IntPtr.Zero, IntPtr.Zero); // Send WM_CLOSE
|
||||
}
|
||||
|
||||
string arguments = $"{UpdateStage.UPDATENOWLAUNCHSTAGE2} \"{installerFilePath}\"";
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(Path.GetTempPath(), "PowerToys.Update.exe"),
|
||||
Arguments = arguments,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = Environment.CurrentDirectory,
|
||||
});
|
||||
}
|
||||
|
||||
private static async Task<string?> DownloadFile(string downloadUri, string downloadFileName)
|
||||
{
|
||||
HttpClient httpClient = new();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("PowerToys Runner"); // GitHub API requires a user-agent
|
||||
|
||||
// 3 Attempts to download the file
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
using FileStream fileStream = new(Path.Combine(_installerPath, downloadFileName), FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
await (await httpClient.GetStreamAsync(downloadUri)).CopyToAsync(fileStream);
|
||||
return fileStream.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void CleanupUpdates()
|
||||
{
|
||||
if (!Path.Exists(_installerPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string file in Directory.GetFiles(_installerPath).Where(f => f.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
private static partial IntPtr FindWindowW(string lpClassName);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool SendMessageW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE" xml:space="preserve">
|
||||
<value>Couldn't download .NET Core Desktop Runtime 3.1, please install it manually.</value>
|
||||
</data>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
|
||||
<value>PowerToys installation error</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
|
||||
<value>An update to PowerToys is available.</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_UPDATE_NOW" xml:space="preserve">
|
||||
<value>Update now</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
|
||||
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_MORE_INFO" xml:space="preserve">
|
||||
<value>More info...</value>
|
||||
</data>
|
||||
<data name="TOAST_TITLE" xml:space="preserve">
|
||||
<value>PowerToys Update</value>
|
||||
</data>
|
||||
</root>
|
||||
22
src/Update/Update.csproj
Normal file
22
src/Update/Update.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\Common.SelfContained.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Description>PowerToys Runner</Description>
|
||||
<AssemblyName>PowerToys.Update</AssemblyName>
|
||||
<OutputPath>..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<_IsPublishing Condition="'$(_IsPublishing)'==''">false</_IsPublishing>
|
||||
</PropertyGroup>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(_IsPublishing)'!='true'">
|
||||
<Exec Command="dotnet publish "$(ProjectPath)" -c $(Configuration) -r $(RuntimeIdentifier) --self-contained -o "$(OutputPath)"" />
|
||||
</Target>
|
||||
</Project>
|
||||
227
src/Update/UpdateSettingsHelper.cs
Normal file
227
src/Update/UpdateSettingsHelper.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public static class UpdateSettingsHelper
|
||||
{
|
||||
private static Thread? _updateThread;
|
||||
|
||||
private const string INSTALLERFILENAME = "powertoyssetup";
|
||||
private const string USERINSTALLERFILENAME = "powertoysusersetup";
|
||||
|
||||
public static void TriggerUpdateCheck()
|
||||
{
|
||||
if (_updateThread is not null && _updateThread.IsAlive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_updateThread = new Thread(async () =>
|
||||
{
|
||||
UpdateInfo updateInfo = await GetUpdateAvailableInfo();
|
||||
switch (updateInfo)
|
||||
{
|
||||
case UpdateInfo.UpdateCheckFailed ucf:
|
||||
ProcessUpdateCheckFailed(ucf);
|
||||
break;
|
||||
case UpdateInfo.UpdateAvailable ua:
|
||||
ProcessUpdateAvailable(ua);
|
||||
break;
|
||||
case UpdateInfo.NoUpdateAvailable:
|
||||
ProcessNoUpdateAvailable();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
_updateThread.Start();
|
||||
}
|
||||
|
||||
internal record UpdateInfo
|
||||
{
|
||||
private UpdateInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public sealed record NoUpdateAvailable : UpdateInfo;
|
||||
|
||||
public sealed record UpdateAvailable(Uri ReleasePageUri, Version AvailableVersion, Uri InstallerDownloadUrl, string InstallerFilename) : UpdateInfo;
|
||||
|
||||
public sealed record UpdateCheckFailed(Exception Exception) : UpdateInfo;
|
||||
}
|
||||
|
||||
internal static async Task<UpdateInfo> GetUpdateAvailableInfo()
|
||||
{
|
||||
Version? currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
if (currentVersion is null)
|
||||
{
|
||||
// Todo: Log
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
|
||||
if (currentVersion is { Major: 0, Minor: 0 })
|
||||
{
|
||||
// Pre-release or local build, skip update check
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HttpClient httpClient = new();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("PowerToys Runner"); // GitHub API requires a user-agent
|
||||
Stream body = await httpClient.GetStreamAsync("https://api.github.com/repos/microsoft/PowerToys/releases/latest").ConfigureAwait(false);
|
||||
JsonElement releaseObject = (await JsonDocument.ParseAsync(body)).RootElement;
|
||||
Version latestVersion = new(releaseObject.GetProperty("tag_name").GetString()?.TrimStart('V', 'v') ?? throw new FormatException("The \"tag_name\" field could not be found"));
|
||||
string architectureString = RuntimeInformation.OSArchitecture switch
|
||||
{
|
||||
Architecture.X64 => "x64",
|
||||
Architecture.Arm64 => "arm64",
|
||||
_ => throw new InvalidDataException("Unknown architecture"),
|
||||
};
|
||||
|
||||
if (latestVersion > currentVersion)
|
||||
{
|
||||
Uri releasePageUri = new(releaseObject.GetProperty("html_url").GetString() ?? throw new FormatException("The \"html_url\" field could not be found"));
|
||||
|
||||
string requiredFilename = GetInstallScope() == InstallScope.PerMachine ? INSTALLERFILENAME : USERINSTALLERFILENAME;
|
||||
|
||||
Uri? installerDownloadUrl = null;
|
||||
string? installerFilename = null;
|
||||
|
||||
foreach (JsonElement asset in releaseObject.GetProperty("assets").EnumerateArray())
|
||||
{
|
||||
string? name = asset.GetProperty("name").GetString();
|
||||
string? browserDownloadUrl = asset.GetProperty("browser_download_url").GetString();
|
||||
|
||||
if (name is null
|
||||
|| browserDownloadUrl is null
|
||||
|| !name.Contains(requiredFilename, StringComparison.InvariantCultureIgnoreCase)
|
||||
|| !name.Contains(".exe", StringComparison.InvariantCultureIgnoreCase)
|
||||
|| !name.Contains(architectureString, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
installerDownloadUrl = new Uri(browserDownloadUrl);
|
||||
installerFilename = name;
|
||||
break;
|
||||
}
|
||||
|
||||
return installerDownloadUrl is null || installerFilename is null
|
||||
? new UpdateInfo.UpdateCheckFailed(new InvalidDataException("No installer found in GitHub release"))
|
||||
: new UpdateInfo.UpdateAvailable(releasePageUri, latestVersion, installerDownloadUrl, installerFilename);
|
||||
}
|
||||
|
||||
return new UpdateInfo.NoUpdateAvailable();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new UpdateInfo.UpdateCheckFailed(e);
|
||||
}
|
||||
}
|
||||
|
||||
private enum InstallScope
|
||||
{
|
||||
PerMachine,
|
||||
PerUser,
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static InstallScope GetInstallScope()
|
||||
{
|
||||
if (Registry.LocalMachine.OpenSubKey(@"Software\Classes\powertoys\", false) is not RegistryKey machineKey)
|
||||
{
|
||||
if (Registry.CurrentUser.OpenSubKey(@"Software\Classes\powertoys\", false) is not RegistryKey userKey)
|
||||
{
|
||||
// Both keys are missing
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
if (userKey.GetValue("InstallScope") is not string installScope)
|
||||
{
|
||||
userKey.Close();
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
userKey.Close();
|
||||
|
||||
return installScope.Contains("perUser") ? InstallScope.PerUser : InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
machineKey.Close();
|
||||
|
||||
return InstallScope.PerMachine;
|
||||
}
|
||||
|
||||
private static readonly string _settingsPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Microsoft",
|
||||
"PowerToys");
|
||||
|
||||
private static readonly string _updatingSettingsFile = Path.Combine(_settingsPath, "UpdateState.json");
|
||||
|
||||
private static void ProcessUpdateAvailable(UpdateInfo.UpdateAvailable updateAvailable)
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
Console.WriteLine($"Update available: {updateAvailable.AvailableVersion}");
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.ReadyToDownload;
|
||||
updatingSettings.ReleasePageLink = updateAvailable.ReleasePageUri.ToString();
|
||||
updatingSettings.DownloadedInstallerFilename = updateAvailable.InstallerFilename;
|
||||
updatingSettings.ReleasePageLink = updateAvailable.ReleasePageUri.ToString();
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static void ProcessNoUpdateAvailable()
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.UpToDate;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.DownloadedInstallerFilename = string.Empty;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
private static void ProcessUpdateCheckFailed(UpdateInfo.UpdateCheckFailed updateCheckFailed)
|
||||
{
|
||||
// Todo: Log failed attempt
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = UpdatingSettings.UpdatingState.NetworkError;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.DownloadedInstallerFilename = string.Empty;
|
||||
updatingSettings.ReleasePageLink = string.Empty;
|
||||
updatingSettings.LastCheckedDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static void SetUpdateState(UpdatingSettings.UpdatingState state)
|
||||
{
|
||||
UpdatingSettings updatingSettings = UpdatingSettings.LoadSettings();
|
||||
|
||||
updatingSettings.State = state;
|
||||
File.WriteAllText(_updatingSettingsFile, updatingSettings.ToJsonString());
|
||||
}
|
||||
|
||||
internal static UpdatingSettings.UpdatingState GetUpdateState() => UpdatingSettings.LoadSettings().State;
|
||||
}
|
||||
}
|
||||
16
src/Update/UpdateStage.cs
Normal file
16
src/Update/UpdateStage.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
internal static class UpdateStage
|
||||
{
|
||||
internal const string UPDATENOWLAUNCHSTAGE1 = "-update_now";
|
||||
internal const string UPDATENOWLAUNCHSTAGE2 = "-update_now_stage_2";
|
||||
}
|
||||
}
|
||||
44
src/Update/UpdateUtilities.cs
Normal file
44
src/Update/UpdateUtilities.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public static class UpdateUtilities
|
||||
{
|
||||
public static async void UninstallPreviousMsixVersions()
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Management.Deployment.PackageManager packageManager = new();
|
||||
var packages = packageManager.FindPackagesForUser(string.Empty, "Microsoft.PowerToys", "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US");
|
||||
|
||||
Version? currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
if (currentVersion == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var package in packages)
|
||||
{
|
||||
Version msixVersion = new(package.Id.Version.Major, package.Id.Version.Minor, package.Id.Version.Revision);
|
||||
if (msixVersion < currentVersion)
|
||||
{
|
||||
await packageManager.RemovePackageAsync(package.Id.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
src/Update/UpdatingSettings.cs
Normal file
124
src/Update/UpdatingSettings.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public sealed class UpdatingSettings
|
||||
{
|
||||
public enum UpdatingState
|
||||
{
|
||||
UpToDate = 0,
|
||||
ErrorDownloading,
|
||||
ReadyToDownload,
|
||||
ReadyToInstall,
|
||||
NetworkError,
|
||||
}
|
||||
|
||||
// Gets or sets a value of the updating state
|
||||
[JsonPropertyName("state")]
|
||||
public UpdatingState State { get; set; }
|
||||
|
||||
// Gets or sets a value of the release page url
|
||||
[JsonPropertyName("releasePageUrl")]
|
||||
public string ReleasePageLink { get; set; } = string.Empty;
|
||||
|
||||
// Gets or sets a value of the github last checked date
|
||||
[JsonPropertyName("githubUpdateLastCheckedDate")]
|
||||
public string LastCheckedDate { get; set; } = string.Empty;
|
||||
|
||||
// Gets or sets a value of the updating state
|
||||
[JsonPropertyName("downloadedInstallerFilename")]
|
||||
public string DownloadedInstallerFilename { get; set; } = string.Empty;
|
||||
|
||||
// Non-localizable strings: Files
|
||||
public const string SettingsFilePath = "\\Microsoft\\PowerToys\\";
|
||||
public const string SettingsFile = "UpdateState.json";
|
||||
|
||||
public string NewVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ReleasePageLink == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string version = ReleasePageLink.Substring(ReleasePageLink.LastIndexOf('/') + 1);
|
||||
return version.Trim();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string LastCheckedDateLocalized
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (LastCheckedDate == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
long seconds = long.Parse(LastCheckedDate, CultureInfo.CurrentCulture);
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(seconds).UtcDateTime;
|
||||
return date.ToLocalTime().ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatingSettings()
|
||||
{
|
||||
State = UpdatingState.UpToDate;
|
||||
}
|
||||
|
||||
public static UpdatingSettings LoadSettings()
|
||||
{
|
||||
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var file = localAppDataDir + SettingsFilePath + SettingsFile;
|
||||
|
||||
if (File.Exists(file))
|
||||
{
|
||||
try
|
||||
{
|
||||
FileStream inputStream = File.Open(file, FileMode.Open);
|
||||
StreamReader reader = new(inputStream);
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
reader.Dispose();
|
||||
|
||||
return JsonSerializer.Deserialize(data, UpdatingsSettingsSourceGenerationContext.Default.UpdatingSettings)!;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return new UpdatingSettings();
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this, UpdatingsSettingsSourceGenerationContext.Default.UpdatingSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/Update/UpdatingsSettingsSourceGenerationContext.cs
Normal file
22
src/Update/UpdatingsSettingsSourceGenerationContext.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(UpdatingSettings))]
|
||||
|
||||
internal sealed partial class UpdatingsSettingsSourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -1,11 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by PowerToys.Update.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys Update"
|
||||
#define INTERNAL_NAME "PowerToys.Update"
|
||||
#define ORIGINAL_FILENAME "PowerToys.Update.exe"
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#include "comUtils.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4067)
|
||||
#include <Sddl.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <memory>
|
||||
#include <wil/resource.h>
|
||||
|
||||
// Helper class for various COM-related APIs, e.g working with security descriptors
|
||||
template<typename T>
|
||||
struct typed_storage
|
||||
{
|
||||
std::unique_ptr<char[]> _buffer;
|
||||
inline explicit typed_storage(const DWORD size) :
|
||||
_buffer{ std::make_unique<char[]>(size) }
|
||||
{
|
||||
}
|
||||
|
||||
inline operator T*()
|
||||
{
|
||||
return reinterpret_cast<T*>(_buffer.get());
|
||||
}
|
||||
};
|
||||
|
||||
bool initializeCOMSecurity(const wchar_t* securityDescriptor)
|
||||
{
|
||||
PSECURITY_DESCRIPTOR self_relative_sd{};
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(securityDescriptor, SDDL_REVISION_1, &self_relative_sd, nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto free_relative_sd = wil::scope_exit([&] {
|
||||
LocalFree(self_relative_sd);
|
||||
});
|
||||
|
||||
DWORD absolute_sd_size = 0;
|
||||
DWORD dacl_size = 0;
|
||||
DWORD group_size = 0;
|
||||
DWORD owner_size = 0;
|
||||
DWORD sacl_size = 0;
|
||||
|
||||
if (!MakeAbsoluteSD(self_relative_sd, nullptr, &absolute_sd_size, nullptr, &dacl_size, nullptr, &sacl_size, nullptr, &owner_size, nullptr, &group_size))
|
||||
{
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
typed_storage<SECURITY_DESCRIPTOR> absolute_sd{ absolute_sd_size };
|
||||
typed_storage<ACL> dacl{ dacl_size };
|
||||
typed_storage<ACL> sacl{ sacl_size };
|
||||
typed_storage<SID> owner{ owner_size };
|
||||
typed_storage<SID> group{ group_size };
|
||||
|
||||
if (!MakeAbsoluteSD(self_relative_sd,
|
||||
absolute_sd,
|
||||
&absolute_sd_size,
|
||||
dacl,
|
||||
&dacl_size,
|
||||
sacl,
|
||||
&sacl_size,
|
||||
owner,
|
||||
&owner_size,
|
||||
group,
|
||||
&group_size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !FAILED(CoInitializeSecurity(
|
||||
absolute_sd,
|
||||
-1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
|
||||
RPC_C_IMP_LEVEL_IDENTIFY,
|
||||
nullptr,
|
||||
EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA,
|
||||
nullptr));
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
bool initializeCOMSecurity(const wchar_t* securityDescriptor);
|
||||
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{7319089E-46D6-4400-BC65-E39BDF1416EE}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>COMUtils</RootNamespace>
|
||||
<ProjectName>COMUtils</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="comUtils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="comUtils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../version/version.h"
|
||||
#include "../utils/version.h"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
|
||||
@@ -98,11 +98,6 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\version\version.vcxproj">
|
||||
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ExprtkEvaluator.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
|
||||
@@ -12,9 +12,13 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="ExprtkEvaluator.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ExprtkEvaluator.h" />
|
||||
<ClInclude Include="exprtk.hpp" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="Calculator.idl" />
|
||||
@@ -26,4 +30,9 @@
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CalculatorEngineCommon.rc">
|
||||
<Filter>Resources</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../common/version/version.h"
|
||||
#include "../../../common/utils/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user