diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt
index 97638a1684..4e28ee7a17 100644
--- a/.github/actions/spell-check/allow/names.txt
+++ b/.github/actions/spell-check/allow/names.txt
@@ -28,6 +28,8 @@ videoconference
# USERS
+# 8LWXpg is user name but user folder causes a flag
+LWXpg
Adoumie
Advaith
alekhyareddy
diff --git a/.github/actions/spell-check/excludes.txt b/.github/actions/spell-check/excludes.txt
index fd89d668a2..fa1d25eda9 100644
--- a/.github/actions/spell-check/excludes.txt
+++ b/.github/actions/spell-check/excludes.txt
@@ -2,11 +2,11 @@
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)3rdparty/
-(?:^|/)FilePreviewCommon/Assets/Monaco/customLanguages/
-(?:^|/)FilePreviewCommon/Assets/Monaco/generateLanguagesJson.html
-(?:^|/)FilePreviewCommon/Assets/Monaco/index.html
-(?:^|/)FilePreviewCommon/Assets/Monaco/monaco_languages.json
-(?:^|/)FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js
+(?:^|/)src/Monaco/customLanguages/
+(?:^|/)src/Monaco/generateLanguagesJson.html
+(?:^|/)src/Monaco/index.html
+(?:^|/)src/Monaco/monaco_languages.json
+(?:^|/)src/Monaco/monacoSpecialLanguages.js
(?:^|/)go\.sum$
(?:^|/)monacoSRC/
(?:^|/)package(?:-lock|)\.json$
@@ -99,7 +99,7 @@
^\Q.pipelines/ESRPSigning_core.json\E$
^\Q.pipelines/sdl.gdnbaselines\E$
^\Qinstaller/PowerToysSetup/Settings.wxs\E$
-^\Qsrc/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json\E$
+^\Qsrc/Monaco/monaco_languages.json\E$
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
^\Qsrc/common/notifications/BackgroundActivatorDLL/cpp.hint\E$
^\Qsrc/modules/colorPicker/ColorPickerUI/Assets/ColorPicker/colorPicker.cur\E$
diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 408f88b372..d3b1c59383 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -2,8 +2,6 @@
## "PackagemanagerWrapper.cs" should be "PackageManagerWrapper.cs"
## NOTICE.MD > MOZILLA PUBLIC LICENSE v1.1
-# user name but user folder causes a flag
-8LWXpg
aaaa
abcdefghjkmnpqrstuvxyz
abgr
@@ -45,6 +43,7 @@ AMPROPSETID
amr
ANDSCANS
animatedvisuals
+anr
ansicolor
ANull
AOC
@@ -60,14 +59,12 @@ APPBARDATA
appdata
APPEXECLINK
Appium
-applayout
Applicationcan
APPLICATIONFRAMEHOST
appmanifest
APPNAME
appref
appsettings
-appsfolder
appwindow
appwiz
APSTUDIO
@@ -148,7 +145,6 @@ BTNFACE
bugreport
BUILDARCH
BUILDNUMBER
-buildtask
buildtransitive
BVal
BValue
@@ -273,7 +269,6 @@ CSettings
cso
CSRW
CStyle
-cswinrt
CSY
CTest
currentculture
@@ -355,7 +350,6 @@ devpkey
DEVSOURCE
DIIRFLAG
dimm
-directshow
DISABLEASACTIONKEY
diskmgmt
DISPLAYCHANGE
@@ -371,7 +365,6 @@ dllmain
DNLEN
DONOTROUND
DONTVALIDATEPATH
-DOPUS
dotnet
DPICHANGED
DPIs
@@ -454,12 +447,13 @@ erwrite
ESettings
esrp
etl
-ETW
+etw
EUQ
eurochange
eventlog
eventvwr
everytime
+evntrace
evt
EWXFORCE
EWXFORCEIFHUNG
@@ -531,7 +525,6 @@ FZE
gacutil
Gaeilge
Gaidhlig
-GBarm
GCLP
gdi
gdiplus
@@ -1002,7 +995,6 @@ NCRENDERING
ndp
NEEDDISPATCH
needinfo
-netcore
netcoreapp
netcpl
netframework
@@ -1011,6 +1003,7 @@ netsh
newcolor
newdev
NEWDIALOGSTYLE
+NEWFILE
newitem
newpath
newplus
@@ -1079,7 +1072,6 @@ NTAPI
ntdll
ntfs
NTSTATUS
-nugets
nullonfailure
numberbox
nwc
@@ -1233,6 +1225,7 @@ proactively
PROCESSENTRY
PROCESSKEY
processthreadsapi
+PROCESSTRACE
PRODEXT
PRODUCTVERSION
Progman
@@ -1274,7 +1267,6 @@ PWSTR
pwsz
pwtd
QDC
-QDir
qianlifeng
qit
QITAB
@@ -1599,9 +1591,7 @@ SYSKEYUP
SYSLIB
SYSMENU
SYSTEMAPPS
-SYSTEMSETTINGS
SYSTEMTIME
-SYSTEMWOW
tapp
TApplication
TApplied
@@ -1621,7 +1611,6 @@ TCustom
tdbuild
TDefault
TDevice
-telem
telephon
templatenamespace
testprocess
@@ -1653,11 +1642,12 @@ toolkitconverters
Toolset
toolwindow
TOPDOWNDIB
-TOTALCMD
TOUCHEVENTF
TOUCHINPUT
touchpad
+TRACEHANDLE
tracelogging
+tracerpt
trafficmanager
traies
transicc
@@ -1717,11 +1707,9 @@ urlmon
Usb
USEDEFAULT
USEFILEATTRIBUTES
-USEPOSITION
USERDATA
Userenv
USESHOWWINDOW
-USESIZE
USESTDHANDLES
USRDLL
UType
@@ -1815,7 +1803,6 @@ wgpocpl
WIC
wil
winapi
-winappdriver
wincodec
Wincodecsdk
wincolor
@@ -1879,6 +1866,7 @@ WNDCLASSEX
WNDCLASSEXW
WNDCLASSW
WNDPROC
+wnode
workarounds
WORKSPACESEDITOR
WORKSPACESLAUNCHER
@@ -1921,9 +1909,9 @@ XFile
XIncrement
XLoc
XNamespace
+Xoshiro
XPels
XPixel
-xplorer
XResource
xsi
XStr
diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json
index c31b6ea184..44ef01bf47 100644
--- a/.pipelines/ESRPSigning_core.json
+++ b/.pipelines/ESRPSigning_core.json
@@ -180,6 +180,7 @@
"PowerToys.FindMyMouse.dll",
"PowerToys.MouseHighlighter.dll",
"PowerToys.MouseJump.dll",
+ "PowerToys.MouseJump.Common.dll",
"PowerToys.MousePointerCrosshairs.dll",
"PowerToys.MouseJumpUI.dll",
"PowerToys.MouseJumpUI.exe",
diff --git a/.pipelines/packages.config b/.pipelines/packages.config
index a5cab593eb..43fa34c91c 100644
--- a/.pipelines/packages.config
+++ b/.pipelines/packages.config
@@ -1,4 +1,4 @@
-
+
diff --git a/.pipelines/v2/release.yml b/.pipelines/v2/release.yml
index b4a6a80833..2719777aa6 100644
--- a/.pipelines/v2/release.yml
+++ b/.pipelines/v2/release.yml
@@ -90,8 +90,8 @@ extends:
- script: |
call nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config || exit /b 1
- move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1
- move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1
+ move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1
+ move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1
displayName: Emplace telemetry files
- stage: Publish
diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml
index 565ba3cab7..40a0e4a866 100644
--- a/.pipelines/v2/templates/job-build-project.yml
+++ b/.pipelines/v2/templates/job-build-project.yml
@@ -143,13 +143,19 @@ jobs:
- pwsh: |-
& '.pipelines/applyXamlStyling.ps1' -Passive
+ displayName: Verify XAML formatting
+
+ - pwsh: |-
& '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
+ displayName: Verify Nuget package versions for PowerToys.sln
+
+ - pwsh: |-
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\BugReportTool\BugReportTool.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\WebcamReportTool\WebcamReportTool.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\StylesReportTool\StylesReportTool.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.sln'
- displayName: Verify formatting, nuget, and ARM64 configurations
+ displayName: Verify ARM64 configurations
- ${{ if eq(parameters.enablePackageCaching, true) }}:
- task: Cache@2
diff --git a/.pipelines/verifyArm64Configuration.ps1 b/.pipelines/verifyArm64Configuration.ps1
index 3a6a9cfe29..a509ec374f 100644
--- a/.pipelines/verifyArm64Configuration.ps1
+++ b/.pipelines/verifyArm64Configuration.ps1
@@ -59,6 +59,7 @@ if ($errorTable.Count -gt 0) {
};
Write-Host -ForegroundColor Red `r
}
+ Write-Error "Found arm64 verification errors."
exit 1;
}
diff --git a/.pipelines/verifyDepsJsonLibraryVersions.ps1 b/.pipelines/verifyDepsJsonLibraryVersions.ps1
index 16ef379188..7d5fc02c10 100644
--- a/.pipelines/verifyDepsJsonLibraryVersions.ps1
+++ b/.pipelines/verifyDepsJsonLibraryVersions.ps1
@@ -15,7 +15,7 @@ Param(
$referencedFileVersionsPerDll = @{}
$totalFailures = 0
-Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones* | ForEach-Object {
+Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones*,MouseJump.Common.UnitTests* | ForEach-Object {
# Temporarily exclude FancyZones UI tests because of Appium.WebDriver dependencies
$depsJsonFullFileName = $_.FullName
$depsJsonFileName = $_.Name
diff --git a/.pipelines/versionAndSignCheck.ps1 b/.pipelines/versionAndSignCheck.ps1
index 1b15fe52db..1baf34570e 100644
--- a/.pipelines/versionAndSignCheck.ps1
+++ b/.pipelines/versionAndSignCheck.ps1
@@ -48,7 +48,7 @@ $totalFailure = 0;
Write-Host $DirPath;
if (-not (Test-Path $DirPath)) {
- Write-Host "Folder does not exist!"
+ Write-Error "Folder does not exist!"
}
Write-Host "Total items: " $items.Count
@@ -79,6 +79,7 @@ $items | ForEach-Object {
}
if ($totalFailure -gt 0) {
+ Write-Error "Some items had issues."
exit 1
}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 1ac74490ff..c0507bda38 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -24,8 +24,11 @@
+
+
+
@@ -57,7 +60,7 @@
-
+
@@ -69,7 +72,7 @@
-
+
diff --git a/NOTICE.md b/NOTICE.md
index 173a453fda..f5882289e5 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1333,8 +1333,10 @@ EXHIBIT A -Mozilla Public License.
- LazyCache 2.4.0
- Mages 2.0.2
- Markdig.Signed 0.34.0
+- MessagePack 2.5.187
- Microsoft.CodeAnalysis.NetAnalyzers 8.0.0
- Microsoft.Data.Sqlite 8.0.7
+- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
- Microsoft.Extensions.DependencyInjection 8.0.0
- Microsoft.Extensions.Hosting 8.0.0
- Microsoft.Extensions.Hosting.WindowsServices 8.0.0
@@ -1358,7 +1360,7 @@ EXHIBIT A -Mozilla Public License.
- ReverseMarkdown 4.1.0
- ScipBe.Common.Office.OneNote 3.0.1
- SharpCompress 0.37.2
-- StreamJsonRpc 2.14.24
+- StreamJsonRpc 2.19.27
- StyleCop.Analyzers 1.2.0-beta.556
- System.CodeDom 8.0.0
- System.CommandLine 2.0.0-beta4.22272.1
@@ -1367,7 +1369,7 @@ EXHIBIT A -Mozilla Public License.
- System.Data.OleDb 8.0.1
- System.Data.SqlClient 4.8.6
- System.Diagnostics.EventLog 8.0.1
-- System.Drawing.Common 8.0.6
+- System.Drawing.Common 8.0.7
- System.IO.Abstractions 17.2.3
- System.IO.Abstractions.TestingHelpers 17.2.3
- System.IO.Hashing 8.0.0
diff --git a/PowerToys.sln b/PowerToys.sln
index 3773a16703..54d758effa 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -178,6 +178,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
Directory.Packages.props = Directory.Packages.props
+ src\Monaco.props = src\Monaco.props
Solution.props = Solution.props
src\Version.props = src\Version.props
EndProjectSection
@@ -298,6 +299,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{
ProjectSection(SolutionItems) = preProject
src\common\Telemetry\ProjectTelemetry.h = src\common\Telemetry\ProjectTelemetry.h
src\common\Telemetry\TelemetryBase.cs = src\common\Telemetry\TelemetryBase.cs
+ src\common\Telemetry\TraceBase.h = src\common\Telemetry\TraceBase.h
src\common\Telemetry\TraceLoggingDefines.h = src\common\Telemetry\TraceLoggingDefines.h
EndProjectSection
EndProject
@@ -505,9 +507,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBordersHelper",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseJump", "src\modules\MouseUtils\MouseJump\MouseJump.vcxproj", "{8A08D663-4995-40E3-B42C-3F910625F284}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\MouseUtils\MouseJumpUI\MouseJumpUI.csproj", "{D962A009-834F-4EEC-AABB-430DF8F98E39}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJump.Common", "src\modules\MouseUtils\MouseJump.Common\MouseJump.Common.csproj", "{923DF87C-CA99-4D1C-B1D2-959174E95BFA}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI.UnitTests", "src\modules\MouseUtils\MouseJumpUI.UnitTests\MouseJumpUI.UnitTests.csproj", "{D9C5DE64-6849-4278-91AD-9660AECF2876}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJump.Common.UnitTests", "src\modules\MouseUtils\MouseJump.Common.UnitTests\MouseJump.Common.UnitTests.csproj", "{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\MouseUtils\MouseJumpUI\MouseJumpUI.csproj", "{D962A009-834F-4EEC-AABB-430DF8F98E39}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdvancedPaste", "AdvancedPaste", "{9873BA05-4C41-4819-9283-CF45D795431B}"
EndProject
@@ -656,6 +660,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLauncher", "src\m
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesWindowArranger", "src\modules\Workspaces\WorkspacesWindowArranger\WorkspacesWindowArranger.vcxproj", "{37D07516-4185-43A4-924F-3C7A5D95ECF6}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBorders.UnitTests", "src\modules\MouseWithoutBorders\MouseWithoutBorders.UnitTests\MouseWithoutBorders.UnitTests.csproj", "{66614C26-314C-4B91-9071-76133422CFEF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -2284,18 +2292,6 @@ Global
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.Build.0 = Release|x64
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.ActiveCfg = Release|x64
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.Build.0 = Release|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.Build.0 = Debug|ARM64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.ActiveCfg = Debug|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.Build.0 = Debug|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.ActiveCfg = Debug|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.Build.0 = Debug|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.ActiveCfg = Release|ARM64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.Build.0 = Release|ARM64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.ActiveCfg = Release|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.Build.0 = Release|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.ActiveCfg = Release|x64
- {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.Build.0 = Release|x64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.Build.0 = Debug|ARM64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.ActiveCfg = Debug|x64
@@ -2840,6 +2836,30 @@ Global
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.ActiveCfg = Release|x64
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.Build.0 = Release|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.Build.0 = Debug|ARM64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.ActiveCfg = Debug|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.Build.0 = Debug|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.ActiveCfg = Debug|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.Build.0 = Debug|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.ActiveCfg = Release|ARM64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.Build.0 = Release|ARM64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.ActiveCfg = Release|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.Build.0 = Release|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.ActiveCfg = Release|x64
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.Build.0 = Release|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.ActiveCfg = Debug|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.Build.0 = Debug|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.ActiveCfg = Debug|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.Build.0 = Debug|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.Build.0 = Release|ARM64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.ActiveCfg = Release|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.Build.0 = Release|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.ActiveCfg = Release|x64
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.Build.0 = Release|x64
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.Build.0 = Debug|ARM64
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|x64.ActiveCfg = Debug|x64
@@ -2924,6 +2944,30 @@ Global
{37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|x64.Build.0 = Release|x64
{37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|x86.ActiveCfg = Release|x64
{37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|x86.Build.0 = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x86.ActiveCfg = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x86.Build.0 = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x86.ActiveCfg = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x86.Build.0 = Release|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|ARM64.Build.0 = Debug|ARM64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x64.ActiveCfg = Debug|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x64.Build.0 = Debug|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x86.ActiveCfg = Debug|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x86.Build.0 = Debug|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|ARM64.ActiveCfg = Release|ARM64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|ARM64.Build.0 = Release|ARM64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|x64.ActiveCfg = Release|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|x64.Build.0 = Release|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|x86.ActiveCfg = Release|x64
+ {66614C26-314C-4B91-9071-76133422CFEF}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3103,7 +3147,6 @@ Global
{A663E672-B26D-4EC0-BEAB-FE2E424AC46F} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
{8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A}
- {D9C5DE64-6849-4278-91AD-9660AECF2876} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B}
{9CE59ED5-7087-4353-88EB-788038A73CEC} = {1AFB6476-670D-4E80-A464-657E01DFF482}
@@ -3157,6 +3200,8 @@ Global
{8ACB33D9-C95B-47D4-8363-9731EE0930A0} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}
{CA716AE6-FE5C-40AC-BB8F-2C87912687AC} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{F055103B-F80B-4D0C-BF48-057C55620033} = {5A7818A8-109C-4E1C-850D-1A654E234B0E}
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{A2221D7E-55E7-4BEA-90D1-4F162D670BBF} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{BE126CBB-AE12-406A-9837-A05ACFCA57A7} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{14CB58B7-D280-4A7A-95DE-4B2DF14EA000} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
@@ -3167,6 +3212,8 @@ Global
{367D7543-7DBA-4381-99F1-BF6142A996C4} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{37D07516-4185-43A4-924F-3C7A5D95ECF6} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD} = {8F62026A-294B-41C6-8839-87463613F216}
+ {66614C26-314C-4B91-9071-76133422CFEF} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
diff --git a/doc/devdocs/common/FilePreviewCommon.md b/doc/devdocs/common/FilePreviewCommon.md
index aee9de2b2a..85b74ca7e7 100644
--- a/doc/devdocs/common/FilePreviewCommon.md
+++ b/doc/devdocs/common/FilePreviewCommon.md
@@ -12,14 +12,14 @@ This previewer is used for the File Explorer Dev File Previewer, as well as Powe
1. Download Monaco editor with [npm](https://www.npmjs.com/): Run `npm i monaco-editor` in the command prompt.
2. Delete everything except the `min` folder (the minimised code) from the downloaded files.
-3. Copy the `min` folder into the `src/common/FilePreviewCommon/Assets/Monaco/monacoSRC` folder of the PowerToys project.
+3. Copy the `min` folder into the `/src/Monaco/monacoSRC` folder of the PowerToys project.
4. Generate the JSON file as described in the generate [monaco_languages.json file](#monaco_languagesjson) section.
### Add a new language definition
-As an example on how to add a new language definition you can look at the one for [registry files](/src/common/FilePreviewCommon/Assets/Monaco/customLanguages/reg.js).
+As an example on how to add a new language definition you can look at the one for [registry files](/src/Monaco/customLanguages/reg.js).
-1. Add the new language definition (written with [Monarch](https://microsoft.github.io/monaco-editor/monarch.html)) as a new file to the [folder containing Monaco custom languages](/src/common/FilePreviewCommon/Assets/Monaco/customLanguages/) (Remember the file name and the string you used for "idDefinition" as you need it later.). The file should be formatted like in the example below. (Please change `idDefinition` to the name of your language.)
+1. Add the new language definition (written with [Monarch](https://microsoft.github.io/monaco-editor/monarch.html)) as a new file to the [folder containing Monaco custom languages](/src/Monaco/customLanguages/) (Remember the file name and the string you used for "idDefinition" as you need it later.). The file should be formatted like in the example below. (Please change `idDefinition` to the name of your language.)
```javascript
export function idDefinition() {
@@ -29,7 +29,7 @@ export function idDefinition() {
}
```
-2. Add the following line to the [`monacoSpecialLanguages.js`](/src/common/FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js) file, after the other import statements:
+2. Add the following line to the [`monacoSpecialLanguages.js`](/src/Monaco/monacoSpecialLanguages.js) file, after the other import statements:
```javascript
import { idDefinition } from './customLanguages/file.js';
@@ -37,7 +37,7 @@ import { idDefinition } from './customLanguages/file.js';
> Replace file.js with the name of your definition file from step 1. Please replace idDefinition with the string you used in step 1.
-3. In the [`monacoSpecialLanguages.js`](/src/common/FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js) file add the following line into the `registerAdditionalLanguages` function:
+3. In the [`monacoSpecialLanguages.js`](/src/Monaco/monacoSpecialLanguages.js) file add the following line into the `registerAdditionalLanguages` function:
```javascript
registerAdditionalNewLanguage("id", [".fileExtension"], idDefinition(), monaco)
@@ -47,7 +47,7 @@ registerAdditionalNewLanguage("id", [".fileExtension"], idDefinition(), monaco)
* The id can be anything. Recommended is one of the file extensions. For example "php" or "reg".
-4. In case you wish to add a custom color for a token, you can do so by adding the following line to [`customTokenColors.js`](/src/common/FilePreviewCommon/Assets/Monaco/customTokenColors.js):
+4. In case you wish to add a custom color for a token, you can do so by adding the following line to [`customTokenColors.js`](/src/Monaco/customTokenColors.js):
```javascript
{token: 'token-name', foreground: 'ff0000'}
```
@@ -60,7 +60,7 @@ registerAdditionalNewLanguage("id", [".fileExtension"], idDefinition(), monaco)
### Add a new file extension to an existing language
-1. In the [`monacoSpecialLanguages.js`](/src/common/FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js) file add the following line to the `registerAdditionalLanguages` function. (`existingId` is the id of the language you want to add the extension to. You can find these id's in the [`monaco_languages.json`](/src/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json) file):
+1. In the [`monacoSpecialLanguages.js`](/src/Monaco/monacoSpecialLanguages.js) file add the following line to the `registerAdditionalLanguages` function. (`existingId` is the id of the language you want to add the extension to. You can find these id's in the [`monaco_languages.json`](/src/Monaco/monaco_languages.json) file):
```javascript
registerAdditionalLanguage("id", [".fileExtension"], "existingId", monaco)
@@ -68,17 +68,17 @@ registerAdditionalLanguage("id", [".fileExtension"], "existingId", monaco)
* If for instance you want to add more extensions to the php language set the id to `phpExt` and the existingId to `php`.
-2. Copy the existing language definition into the `languageDefinitions` function in the same file. You can find the existing definitions in the following folder: [`/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/`](/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/).
+2. Copy the existing language definition into the `languageDefinitions` function in the same file. You can find the existing definitions in the following folder: [`/src/Monaco/monacoSRC/min/vs/basic-languages/`](/src/Monaco/monacoSRC/min/vs/basic-languages/).
3. Execute the steps described in the [monaco_languages.json](#monaco_languagesjson) section.
### monaco_languages.json
-[`monaco_languages.json`](/src/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json) contains all extensions and IDs for the languages supported by Monaco. The [`MonacoHelper`](/src/common/FilePreviewCommon/MonacoHelper.cs) class and the installer are using this file to register preview handlers for the defined extensions.
+[`monaco_languages.json`](/src/Monaco/monaco_languages.json) contains all extensions and IDs for the languages supported by Monaco. The [`MonacoHelper`](/src/common/FilePreviewCommon/MonacoHelper.cs) class and the installer are using this file to register preview handlers for the defined extensions.
-After updating Monaco Editor and/or adding a new language you should update the [`monaco_languages.json`](/src/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json) file.
+After updating Monaco Editor and/or adding a new language you should update the [`monaco_languages.json`](/src/Monaco/monaco_languages.json) file.
-1. Run the [`generateLanguagesJson.html`](/src/common/FilePreviewCommon/Assets/Monaco/generateLanguagesJson.html) file on a local webserver (as webbrowsers will block certain needed features when running the file locally.)
+1. Run the [`generateLanguagesJson.html`](/src/Monaco/generateLanguagesJson.html) file on a local webserver (as webbrowsers will block certain needed features when running the file locally.)
* This can for example be achieved by using the [Preview Server](https://marketplace.visualstudio.com/items?itemName=yuichinukiyama.vscode-preview-server) extension for Visual Studio Code: Open the file in Visual Studio Code, right click in the code editor and select `vscode-preview-server: Launch on browser`. The file will be opened in a browser.
2. The browser will download the new `monaco_languages.json` file
3. Replace the old file with the newly downloaded one in the source code folder.
diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md
index 4f58b1bea5..ad9b417b39 100644
--- a/doc/thirdPartyRunPlugins.md
+++ b/doc/thirdPartyRunPlugins.md
@@ -57,3 +57,4 @@ Below are community created plugins that target a website or software. They are
| [Spotify](https://github.com/waaverecords/PowerToys-Run-Spotify) | [waaverecords](https://github.com/waaverecords) | Search Spotify and control its player |
| [PowerSearch for 1Password](https://github.com/KairuDeibisu/PowerToysRunPlugin1Password) | [KairuDeibisu](https://github.com/KairuDeibisu) | An unofficial plugin for searching 1Password for usernames and passwords |
| [HackMD](https://github.com/8LWXpg/PowerToysRun-HackMD) | [8LWXpg](https://github.com/8LWXpg) | Open HackMD notes |
+| [SSH](https://github.com/8LWXpg/PowerToysRun-SSH) | [8LWXpg](https://github.com/8LWXpg) | Connect to ssh clients |
diff --git a/installer/PowerToysSetup.sln b/installer/PowerToysSetup.sln
index cdcef54079..540ef43d23 100644
--- a/installer/PowerToysSetup.sln
+++ b/installer/PowerToysSetup.sln
@@ -15,6 +15,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysBootstrapper", "Po
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "..\src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -68,6 +70,14 @@ Global
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.Build.0 = Release|ARM64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64
+ {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/installer/PowerToysSetup/PowerToysInstaller.wixproj b/installer/PowerToysSetup/PowerToysInstaller.wixproj
index 4e83930fef..4bad4b72b3 100644
--- a/installer/PowerToysSetup/PowerToysInstaller.wixproj
+++ b/installer/PowerToysSetup/PowerToysInstaller.wixproj
@@ -183,7 +183,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
-->
-
+
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp
index 0ddf039851..d011156a0d 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.cpp
+++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp
@@ -10,6 +10,7 @@
#include "../../src/common/utils/modulesRegistry.h"
#include "../../src/common/updating/installer.h"
#include "../../src/common/version/version.h"
+#include "../../src/common/Telemetry/EtwTrace/EtwTrace.h"
#include
#include
@@ -27,9 +28,9 @@ HINSTANCE DLL_HANDLE = nullptr;
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
- "Microsoft.PowerToysInstaller",
- // {e1d8165d-5cb6-5c74-3b51-bdfbfe4f7a3b}
- (0xe1d8165d, 0x5cb6, 0x5c74, 0x3b, 0x51, 0xbd, 0xfb, 0xfe, 0x4f, 0x7a, 0x3b),
+ "Microsoft.PowerToys",
+ // {38e8889b-9731-53f5-e901-e8a7c1753074}
+ (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
@@ -38,6 +39,53 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
+constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
+constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
+
+#define TraceLoggingWriteWrapper(provider, eventName, ...) \
+ if (isDataDiagnosticEnabled()) \
+ { \
+ trace.UpdateState(true); \
+ TraceLoggingWrite(provider, eventName, __VA_ARGS__); \
+ trace.Flush(); \
+ trace.UpdateState(false); \
+ }
+
+static Shared::Trace::ETWTrace trace{ L"PowerToys_Installer" };
+
+inline bool isDataDiagnosticEnabled()
+{
+ HKEY key{};
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ 0,
+ KEY_READ,
+ &key) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ DWORD isDataDiagnosticsEnabled = 0;
+ DWORD size = sizeof(isDataDiagnosticsEnabled);
+
+ if (RegGetValueW(
+ HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ DataDiagnosticsRegValueName,
+ RRF_RT_REG_DWORD,
+ nullptr,
+ &isDataDiagnosticsEnabled,
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return false;
+ }
+ RegCloseKey(key);
+
+ return isDataDiagnosticsEnabled == 1;
+}
+
+
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
{
DWORD len = 0;
@@ -793,13 +841,14 @@ UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogInstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Install_Success",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
- TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)
+ );
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
@@ -814,7 +863,7 @@ UINT __stdcall TelemetryLogInstallCancelCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogInstallCancelCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Install_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -835,7 +884,7 @@ UINT __stdcall TelemetryLogInstallFailCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogInstallFailCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Install_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -856,7 +905,7 @@ UINT __stdcall TelemetryLogUninstallSuccessCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogUninstallSuccessCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"UnInstall_Success",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -877,7 +926,7 @@ UINT __stdcall TelemetryLogUninstallCancelCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogUninstallCancelCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"UnInstall_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -898,7 +947,7 @@ UINT __stdcall TelemetryLogUninstallFailCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogUninstallFailCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"UnInstall_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -919,7 +968,7 @@ UINT __stdcall TelemetryLogRepairCancelCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogRepairCancelCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Repair_Cancel",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
@@ -940,7 +989,7 @@ UINT __stdcall TelemetryLogRepairFailCA(MSIHANDLE hInstall)
hr = WcaInitialize(hInstall, "TelemetryLogRepairFailCA");
ExitOnFailure(hr, "Failed to initialize");
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Repair_Fail",
TraceLoggingWideString(get_product_version().c_str(), "Version"),
diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
index 61f8599479..56ff9b808a 100644
--- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
+++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
@@ -162,6 +162,9 @@
{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
diff --git a/src/Monaco.props b/src/Monaco.props
new file mode 100644
index 0000000000..0aeef121e2
--- /dev/null
+++ b/src/Monaco.props
@@ -0,0 +1,30 @@
+
+
+
+
+
+ Assets\Monaco\customTokenColors.js
+ Always
+
+
+ Assets\Monaco\monacoSpecialLanguages.js
+ Always
+
+
+ Assets\Monaco\index.html
+ Always
+
+
+ Assets\Monaco\monaco_languages.json
+ Always
+
+
+ Assets\Monaco\monacoSRC\%(RecursiveDir)%(FileName)%(Extension)
+ Always
+
+
+ Assets\Monaco\customLanguages\%(RecursiveDir)%(FileName)%(Extension)
+ Always
+
+
+
\ No newline at end of file
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/customLanguages/gitignore.js b/src/Monaco/customLanguages/gitignore.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/customLanguages/gitignore.js
rename to src/Monaco/customLanguages/gitignore.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/customLanguages/reg.js b/src/Monaco/customLanguages/reg.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/customLanguages/reg.js
rename to src/Monaco/customLanguages/reg.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/customTokenColors.js b/src/Monaco/customTokenColors.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/customTokenColors.js
rename to src/Monaco/customTokenColors.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/generateLanguagesJson.html b/src/Monaco/generateLanguagesJson.html
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/generateLanguagesJson.html
rename to src/Monaco/generateLanguagesJson.html
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/index.html b/src/Monaco/index.html
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/index.html
rename to src/Monaco/index.html
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/Monaco/monacoSRC/min/vs/base/browser/ui/codicons/codicon/codicon.ttf
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/browser/ui/codicons/codicon/codicon.ttf
rename to src/Monaco/monacoSRC/min/vs/base/browser/ui/codicons/codicon/codicon.ttf
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.de.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.de.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.de.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.de.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.es.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.es.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.es.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.es.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.fr.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.fr.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.fr.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.fr.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.it.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.it.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.it.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.it.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ja.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ja.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ja.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ja.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ko.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ko.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ko.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ko.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ru.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ru.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ru.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.ru.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js b/src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js
rename to src/Monaco/monacoSRC/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/worker/workerMain.js b/src/Monaco/monacoSRC/min/vs/base/worker/workerMain.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/base/worker/workerMain.js
rename to src/Monaco/monacoSRC/min/vs/base/worker/workerMain.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/abap/abap.js b/src/Monaco/monacoSRC/min/vs/basic-languages/abap/abap.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/abap/abap.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/abap/abap.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/apex/apex.js b/src/Monaco/monacoSRC/min/vs/basic-languages/apex/apex.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/apex/apex.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/apex/apex.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/azcli/azcli.js b/src/Monaco/monacoSRC/min/vs/basic-languages/azcli/azcli.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/azcli/azcli.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/azcli/azcli.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/bat/bat.js b/src/Monaco/monacoSRC/min/vs/basic-languages/bat/bat.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/bat/bat.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/bat/bat.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/bicep/bicep.js b/src/Monaco/monacoSRC/min/vs/basic-languages/bicep/bicep.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/bicep/bicep.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/bicep/bicep.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cameligo/cameligo.js b/src/Monaco/monacoSRC/min/vs/basic-languages/cameligo/cameligo.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cameligo/cameligo.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/cameligo/cameligo.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/clojure/clojure.js b/src/Monaco/monacoSRC/min/vs/basic-languages/clojure/clojure.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/clojure/clojure.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/clojure/clojure.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/coffee/coffee.js b/src/Monaco/monacoSRC/min/vs/basic-languages/coffee/coffee.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/coffee/coffee.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/coffee/coffee.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cpp/cpp.js b/src/Monaco/monacoSRC/min/vs/basic-languages/cpp/cpp.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cpp/cpp.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/cpp/cpp.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/csharp/csharp.js b/src/Monaco/monacoSRC/min/vs/basic-languages/csharp/csharp.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/csharp/csharp.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/csharp/csharp.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/csp/csp.js b/src/Monaco/monacoSRC/min/vs/basic-languages/csp/csp.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/csp/csp.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/csp/csp.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/css/css.js b/src/Monaco/monacoSRC/min/vs/basic-languages/css/css.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/css/css.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/css/css.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cypher/cypher.js b/src/Monaco/monacoSRC/min/vs/basic-languages/cypher/cypher.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/cypher/cypher.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/cypher/cypher.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/dart/dart.js b/src/Monaco/monacoSRC/min/vs/basic-languages/dart/dart.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/dart/dart.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/dart/dart.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/dockerfile/dockerfile.js b/src/Monaco/monacoSRC/min/vs/basic-languages/dockerfile/dockerfile.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/dockerfile/dockerfile.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/dockerfile/dockerfile.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ecl/ecl.js b/src/Monaco/monacoSRC/min/vs/basic-languages/ecl/ecl.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ecl/ecl.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/ecl/ecl.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/elixir/elixir.js b/src/Monaco/monacoSRC/min/vs/basic-languages/elixir/elixir.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/elixir/elixir.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/elixir/elixir.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/flow9/flow9.js b/src/Monaco/monacoSRC/min/vs/basic-languages/flow9/flow9.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/flow9/flow9.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/flow9/flow9.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/freemarker2/freemarker2.js b/src/Monaco/monacoSRC/min/vs/basic-languages/freemarker2/freemarker2.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/freemarker2/freemarker2.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/freemarker2/freemarker2.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/fsharp/fsharp.js b/src/Monaco/monacoSRC/min/vs/basic-languages/fsharp/fsharp.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/fsharp/fsharp.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/fsharp/fsharp.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/go/go.js b/src/Monaco/monacoSRC/min/vs/basic-languages/go/go.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/go/go.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/go/go.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/graphql/graphql.js b/src/Monaco/monacoSRC/min/vs/basic-languages/graphql/graphql.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/graphql/graphql.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/graphql/graphql.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/handlebars/handlebars.js b/src/Monaco/monacoSRC/min/vs/basic-languages/handlebars/handlebars.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/handlebars/handlebars.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/handlebars/handlebars.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/hcl/hcl.js b/src/Monaco/monacoSRC/min/vs/basic-languages/hcl/hcl.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/hcl/hcl.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/hcl/hcl.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/html/html.js b/src/Monaco/monacoSRC/min/vs/basic-languages/html/html.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/html/html.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/html/html.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ini/ini.js b/src/Monaco/monacoSRC/min/vs/basic-languages/ini/ini.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ini/ini.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/ini/ini.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/java/java.js b/src/Monaco/monacoSRC/min/vs/basic-languages/java/java.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/java/java.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/java/java.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/javascript/javascript.js b/src/Monaco/monacoSRC/min/vs/basic-languages/javascript/javascript.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/javascript/javascript.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/javascript/javascript.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/julia/julia.js b/src/Monaco/monacoSRC/min/vs/basic-languages/julia/julia.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/julia/julia.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/julia/julia.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/kotlin/kotlin.js b/src/Monaco/monacoSRC/min/vs/basic-languages/kotlin/kotlin.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/kotlin/kotlin.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/kotlin/kotlin.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/less/less.js b/src/Monaco/monacoSRC/min/vs/basic-languages/less/less.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/less/less.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/less/less.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/lexon/lexon.js b/src/Monaco/monacoSRC/min/vs/basic-languages/lexon/lexon.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/lexon/lexon.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/lexon/lexon.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/liquid/liquid.js b/src/Monaco/monacoSRC/min/vs/basic-languages/liquid/liquid.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/liquid/liquid.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/liquid/liquid.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/lua/lua.js b/src/Monaco/monacoSRC/min/vs/basic-languages/lua/lua.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/lua/lua.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/lua/lua.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/m3/m3.js b/src/Monaco/monacoSRC/min/vs/basic-languages/m3/m3.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/m3/m3.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/m3/m3.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/markdown/markdown.js b/src/Monaco/monacoSRC/min/vs/basic-languages/markdown/markdown.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/markdown/markdown.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/markdown/markdown.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mdx/mdx.js b/src/Monaco/monacoSRC/min/vs/basic-languages/mdx/mdx.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mdx/mdx.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/mdx/mdx.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mips/mips.js b/src/Monaco/monacoSRC/min/vs/basic-languages/mips/mips.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mips/mips.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/mips/mips.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/msdax/msdax.js b/src/Monaco/monacoSRC/min/vs/basic-languages/msdax/msdax.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/msdax/msdax.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/msdax/msdax.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mysql/mysql.js b/src/Monaco/monacoSRC/min/vs/basic-languages/mysql/mysql.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/mysql/mysql.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/mysql/mysql.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/objective-c/objective-c.js b/src/Monaco/monacoSRC/min/vs/basic-languages/objective-c/objective-c.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/objective-c/objective-c.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/objective-c/objective-c.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pascal/pascal.js b/src/Monaco/monacoSRC/min/vs/basic-languages/pascal/pascal.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pascal/pascal.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/pascal/pascal.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pascaligo/pascaligo.js b/src/Monaco/monacoSRC/min/vs/basic-languages/pascaligo/pascaligo.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pascaligo/pascaligo.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/pascaligo/pascaligo.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/perl/perl.js b/src/Monaco/monacoSRC/min/vs/basic-languages/perl/perl.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/perl/perl.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/perl/perl.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pgsql/pgsql.js b/src/Monaco/monacoSRC/min/vs/basic-languages/pgsql/pgsql.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pgsql/pgsql.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/pgsql/pgsql.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/php/php.js b/src/Monaco/monacoSRC/min/vs/basic-languages/php/php.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/php/php.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/php/php.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pla/pla.js b/src/Monaco/monacoSRC/min/vs/basic-languages/pla/pla.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pla/pla.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/pla/pla.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/postiats/postiats.js b/src/Monaco/monacoSRC/min/vs/basic-languages/postiats/postiats.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/postiats/postiats.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/postiats/postiats.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/powerquery/powerquery.js b/src/Monaco/monacoSRC/min/vs/basic-languages/powerquery/powerquery.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/powerquery/powerquery.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/powerquery/powerquery.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/powershell/powershell.js b/src/Monaco/monacoSRC/min/vs/basic-languages/powershell/powershell.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/powershell/powershell.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/powershell/powershell.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/protobuf/protobuf.js b/src/Monaco/monacoSRC/min/vs/basic-languages/protobuf/protobuf.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/protobuf/protobuf.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/protobuf/protobuf.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pug/pug.js b/src/Monaco/monacoSRC/min/vs/basic-languages/pug/pug.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/pug/pug.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/pug/pug.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/python/python.js b/src/Monaco/monacoSRC/min/vs/basic-languages/python/python.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/python/python.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/python/python.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/qsharp/qsharp.js b/src/Monaco/monacoSRC/min/vs/basic-languages/qsharp/qsharp.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/qsharp/qsharp.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/qsharp/qsharp.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/r/r.js b/src/Monaco/monacoSRC/min/vs/basic-languages/r/r.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/r/r.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/r/r.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/razor/razor.js b/src/Monaco/monacoSRC/min/vs/basic-languages/razor/razor.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/razor/razor.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/razor/razor.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/redis/redis.js b/src/Monaco/monacoSRC/min/vs/basic-languages/redis/redis.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/redis/redis.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/redis/redis.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/redshift/redshift.js b/src/Monaco/monacoSRC/min/vs/basic-languages/redshift/redshift.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/redshift/redshift.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/redshift/redshift.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/restructuredtext/restructuredtext.js b/src/Monaco/monacoSRC/min/vs/basic-languages/restructuredtext/restructuredtext.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/restructuredtext/restructuredtext.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/restructuredtext/restructuredtext.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ruby/ruby.js b/src/Monaco/monacoSRC/min/vs/basic-languages/ruby/ruby.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/ruby/ruby.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/ruby/ruby.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/rust/rust.js b/src/Monaco/monacoSRC/min/vs/basic-languages/rust/rust.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/rust/rust.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/rust/rust.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sb/sb.js b/src/Monaco/monacoSRC/min/vs/basic-languages/sb/sb.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sb/sb.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/sb/sb.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scala/scala.js b/src/Monaco/monacoSRC/min/vs/basic-languages/scala/scala.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scala/scala.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/scala/scala.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scheme/scheme.js b/src/Monaco/monacoSRC/min/vs/basic-languages/scheme/scheme.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scheme/scheme.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/scheme/scheme.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scss/scss.js b/src/Monaco/monacoSRC/min/vs/basic-languages/scss/scss.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/scss/scss.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/scss/scss.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/shell/shell.js b/src/Monaco/monacoSRC/min/vs/basic-languages/shell/shell.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/shell/shell.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/shell/shell.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/solidity/solidity.js b/src/Monaco/monacoSRC/min/vs/basic-languages/solidity/solidity.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/solidity/solidity.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/solidity/solidity.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sophia/sophia.js b/src/Monaco/monacoSRC/min/vs/basic-languages/sophia/sophia.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sophia/sophia.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/sophia/sophia.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sparql/sparql.js b/src/Monaco/monacoSRC/min/vs/basic-languages/sparql/sparql.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sparql/sparql.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/sparql/sparql.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sql/sql.js b/src/Monaco/monacoSRC/min/vs/basic-languages/sql/sql.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/sql/sql.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/sql/sql.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/st/st.js b/src/Monaco/monacoSRC/min/vs/basic-languages/st/st.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/st/st.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/st/st.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/swift/swift.js b/src/Monaco/monacoSRC/min/vs/basic-languages/swift/swift.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/swift/swift.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/swift/swift.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/systemverilog/systemverilog.js b/src/Monaco/monacoSRC/min/vs/basic-languages/systemverilog/systemverilog.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/systemverilog/systemverilog.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/systemverilog/systemverilog.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/tcl/tcl.js b/src/Monaco/monacoSRC/min/vs/basic-languages/tcl/tcl.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/tcl/tcl.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/tcl/tcl.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/twig/twig.js b/src/Monaco/monacoSRC/min/vs/basic-languages/twig/twig.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/twig/twig.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/twig/twig.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/typescript/typescript.js b/src/Monaco/monacoSRC/min/vs/basic-languages/typescript/typescript.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/typescript/typescript.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/typescript/typescript.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/vb/vb.js b/src/Monaco/monacoSRC/min/vs/basic-languages/vb/vb.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/vb/vb.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/vb/vb.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/wgsl/wgsl.js b/src/Monaco/monacoSRC/min/vs/basic-languages/wgsl/wgsl.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/wgsl/wgsl.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/wgsl/wgsl.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/xml/xml.js b/src/Monaco/monacoSRC/min/vs/basic-languages/xml/xml.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/xml/xml.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/xml/xml.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/yaml/yaml.js b/src/Monaco/monacoSRC/min/vs/basic-languages/yaml/yaml.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/basic-languages/yaml/yaml.js
rename to src/Monaco/monacoSRC/min/vs/basic-languages/yaml/yaml.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.css b/src/Monaco/monacoSRC/min/vs/editor/editor.main.css
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.css
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.css
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.de.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.de.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.de.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.de.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.es.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.es.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.es.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.es.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.fr.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.fr.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.fr.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.fr.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.it.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.it.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.it.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.it.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ja.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ja.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ja.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ja.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ko.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ko.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ko.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ko.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ru.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ru.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ru.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.ru.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-cn.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-cn.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-cn.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-cn.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-tw.js b/src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-tw.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-tw.js
rename to src/Monaco/monacoSRC/min/vs/editor/editor.main.nls.zh-tw.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/css/cssMode.js b/src/Monaco/monacoSRC/min/vs/language/css/cssMode.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/css/cssMode.js
rename to src/Monaco/monacoSRC/min/vs/language/css/cssMode.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/css/cssWorker.js b/src/Monaco/monacoSRC/min/vs/language/css/cssWorker.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/css/cssWorker.js
rename to src/Monaco/monacoSRC/min/vs/language/css/cssWorker.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/html/htmlMode.js b/src/Monaco/monacoSRC/min/vs/language/html/htmlMode.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/html/htmlMode.js
rename to src/Monaco/monacoSRC/min/vs/language/html/htmlMode.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/html/htmlWorker.js b/src/Monaco/monacoSRC/min/vs/language/html/htmlWorker.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/html/htmlWorker.js
rename to src/Monaco/monacoSRC/min/vs/language/html/htmlWorker.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/json/jsonMode.js b/src/Monaco/monacoSRC/min/vs/language/json/jsonMode.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/json/jsonMode.js
rename to src/Monaco/monacoSRC/min/vs/language/json/jsonMode.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/json/jsonWorker.js b/src/Monaco/monacoSRC/min/vs/language/json/jsonWorker.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/json/jsonWorker.js
rename to src/Monaco/monacoSRC/min/vs/language/json/jsonWorker.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/typescript/tsMode.js b/src/Monaco/monacoSRC/min/vs/language/typescript/tsMode.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/typescript/tsMode.js
rename to src/Monaco/monacoSRC/min/vs/language/typescript/tsMode.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/typescript/tsWorker.js b/src/Monaco/monacoSRC/min/vs/language/typescript/tsWorker.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/language/typescript/tsWorker.js
rename to src/Monaco/monacoSRC/min/vs/language/typescript/tsWorker.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/loader.js b/src/Monaco/monacoSRC/min/vs/loader.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSRC/min/vs/loader.js
rename to src/Monaco/monacoSRC/min/vs/loader.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js b/src/Monaco/monacoSpecialLanguages.js
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monacoSpecialLanguages.js
rename to src/Monaco/monacoSpecialLanguages.js
diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json b/src/Monaco/monaco_languages.json
similarity index 100%
rename from src/common/FilePreviewCommon/Assets/Monaco/monaco_languages.json
rename to src/Monaco/monaco_languages.json
diff --git a/src/common/FilePreviewCommon/FilePreviewCommon.csproj b/src/common/FilePreviewCommon/FilePreviewCommon.csproj
index 4dfb425f37..28865605a0 100644
--- a/src/common/FilePreviewCommon/FilePreviewCommon.csproj
+++ b/src/common/FilePreviewCommon/FilePreviewCommon.csproj
@@ -1,6 +1,7 @@
+
PowerToys FilePreviewCommon
@@ -15,28 +16,4 @@
-
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp
index dc370fc517..f8afd14073 100644
--- a/src/common/GPOWrapper/GPOWrapper.cpp
+++ b/src/common/GPOWrapper/GPOWrapper.cpp
@@ -228,4 +228,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation
{
return static_cast(powertoys_gpo::getConfiguredNewPlusHideTemplateFilenameExtensionValue());
}
+ GpoRuleConfigured GPOWrapper::GetAllowDataDiagnosticsValue()
+ {
+ return static_cast(powertoys_gpo::getAllowDataDiagnosticsValue());
+ }
}
diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h
index 881ab12051..fc43ad2309 100644
--- a/src/common/GPOWrapper/GPOWrapper.h
+++ b/src/common/GPOWrapper/GPOWrapper.h
@@ -62,6 +62,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
static winrt::hstring GPOWrapper::GetConfiguredMwbPolicyDefinedIpMappingRules();
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
+ static GpoRuleConfigured GetAllowDataDiagnosticsValue();
};
}
diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl
index a00ff83372..1068896d5d 100644
--- a/src/common/GPOWrapper/GPOWrapper.idl
+++ b/src/common/GPOWrapper/GPOWrapper.idl
@@ -66,6 +66,7 @@ namespace PowerToys
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
static String GetConfiguredMwbPolicyDefinedIpMappingRules();
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
+ static GpoRuleConfigured GetAllowDataDiagnosticsValue();
}
}
}
diff --git a/src/common/ManagedCommon/Logger.cs b/src/common/ManagedCommon/Logger.cs
index 416a7aa042..bbc2637fd9 100644
--- a/src/common/ManagedCommon/Logger.cs
+++ b/src/common/ManagedCommon/Logger.cs
@@ -60,14 +60,29 @@ namespace ManagedCommon
public static void LogError(string message, Exception ex)
{
- Log(
- message + Environment.NewLine +
- ex?.Message + Environment.NewLine +
- "Inner exception: " + Environment.NewLine +
- ex?.InnerException?.Message + Environment.NewLine +
- "Stack trace: " + Environment.NewLine +
- ex?.StackTrace,
- Error);
+ if (ex == null)
+ {
+ LogError(message);
+ }
+ else
+ {
+ var exMessage =
+ message + Environment.NewLine +
+ ex.GetType() + ": " + ex.Message + Environment.NewLine;
+
+ if (ex.InnerException != null)
+ {
+ exMessage +=
+ "Inner exception: " + Environment.NewLine +
+ ex.InnerException.GetType() + ": " + ex.InnerException.Message + Environment.NewLine;
+ }
+
+ exMessage +=
+ "Stack trace: " + Environment.NewLine +
+ ex.StackTrace;
+
+ Log(exMessage, Error);
+ }
}
public static void LogWarning(string message)
diff --git a/src/common/ManagedTelemetry/Telemetry/DataDiagnosticsSettings.cs b/src/common/ManagedTelemetry/Telemetry/DataDiagnosticsSettings.cs
new file mode 100644
index 0000000000..0a9aa7c891
--- /dev/null
+++ b/src/common/ManagedTelemetry/Telemetry/DataDiagnosticsSettings.cs
@@ -0,0 +1,107 @@
+// 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 Microsoft.Win32;
+
+namespace Microsoft.PowerToys.Telemetry
+{
+ public static class DataDiagnosticsSettings
+ {
+ private static readonly string DataDiagnosticsRegistryKey = @"HKEY_CURRENT_USER\Software\Classes\PowerToys\";
+ private static readonly string DataDiagnosticsRegistryValueName = @"AllowDataDiagnostics";
+ private static readonly string DataDiagnosticsDataDiagnosticsUserActionRegistryValueName = @"DataDiagnosticsUserAction";
+ private static readonly string DataDiagnosticsDataDiagnosticsViewDataRegistryValueName = @"DataDiagnosticsViewEnabled";
+
+ public static bool GetEnabledValue()
+ {
+ object registryValue = null;
+ try
+ {
+ registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsRegistryValueName, 0);
+ }
+ catch
+ {
+ }
+
+ if (registryValue is not null)
+ {
+ return (int)registryValue == 1 ? true : false;
+ }
+
+ return false;
+ }
+
+ public static void SetEnabledValue(bool value)
+ {
+ try
+ {
+ Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsRegistryValueName, value ? 1 : 0);
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ public static bool GetUserActionValue()
+ {
+ object registryValue = null;
+ try
+ {
+ registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsUserActionRegistryValueName, 0);
+ }
+ catch
+ {
+ }
+
+ if (registryValue is not null)
+ {
+ return (int)registryValue == 1 ? true : false;
+ }
+
+ return false;
+ }
+
+ public static void SetUserActionValue(bool value)
+ {
+ try
+ {
+ Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsUserActionRegistryValueName, value ? 1 : 0);
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ public static bool GetViewEnabledValue()
+ {
+ object registryValue = null;
+ try
+ {
+ registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsViewDataRegistryValueName, 0);
+ }
+ catch
+ {
+ }
+
+ if (registryValue is not null)
+ {
+ return (int)registryValue == 1 ? true : false;
+ }
+
+ return false;
+ }
+
+ public static void SetViewEnabledValue(bool value)
+ {
+ try
+ {
+ Registry.SetValue(DataDiagnosticsRegistryKey, DataDiagnosticsDataDiagnosticsViewDataRegistryValueName, value ? 1 : 0);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+}
diff --git a/src/common/ManagedTelemetry/Telemetry/EtwTrace.cs b/src/common/ManagedTelemetry/Telemetry/EtwTrace.cs
new file mode 100644
index 0000000000..d1d3ec2456
--- /dev/null
+++ b/src/common/ManagedTelemetry/Telemetry/EtwTrace.cs
@@ -0,0 +1,158 @@
+// 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.Diagnostics.Tracing;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Diagnostics.Tracing.Session;
+
+namespace Microsoft.PowerToys.Telemetry
+{
+ ///
+ /// This class is based loosely on the C++ ETWTrace class in Win32client/Framework project.
+ /// It is intended to record telemetry events generated by the PowerToys processes so that end users
+ /// can view them if they want.
+ ///
+ public class ETWTrace : IDisposable
+ {
+ internal const EventKeywords TelemetryKeyword = (EventKeywords)0x0000200000000000;
+ internal const EventKeywords MeasuresKeyword = (EventKeywords)0x0000400000000000;
+ internal const EventKeywords CriticalDataKeyword = (EventKeywords)0x0000800000000000;
+
+ private readonly bool telemetryEnabled = DataDiagnosticsSettings.GetEnabledValue(); // This is the global telemetry setting on whether to log events
+ private readonly bool telemetryRecordingEnabled = DataDiagnosticsSettings.GetViewEnabledValue(); // This is the setting for recording telemetry events to disk for viewing
+ private readonly string etwFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\PowerToys\", "etw");
+ private bool disposedValue;
+ private string sessionName;
+ private string etwFilePath;
+ private bool started;
+#nullable enable
+ private TraceEventSession? traceSession;
+
+ internal sealed class Lister : EventListener
+ {
+ public Lister()
+ : base()
+ {
+ }
+ }
+
+ private Lister? listener;
+#nullable disable
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ETWTrace()
+ {
+ if (File.Exists(etwFolderPath))
+ {
+ File.Delete(etwFolderPath);
+ }
+
+ if (!Directory.Exists(etwFolderPath))
+ {
+ Directory.CreateDirectory(etwFolderPath);
+ }
+
+ if (this.telemetryEnabled && this.telemetryRecordingEnabled)
+ {
+ this.Start();
+ }
+
+ listener = new Lister();
+ listener.EnableEvents(PowerToysTelemetry.Log, EventLevel.LogAlways);
+ }
+
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ this.Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Starts the trace session.
+ ///
+ public void Start()
+ {
+ lock (this)
+ {
+ if (this.started)
+ {
+ return;
+ }
+
+ new Task(() =>
+ {
+ while (true)
+ {
+ Thread.Sleep(30 * 1000);
+
+ this.traceSession.Flush();
+ }
+ }).Start();
+
+ string executable = Process.GetCurrentProcess().ProcessName;
+ string dateTimeNow = DateTime.Now.ToString("MM-d-yyyy__H_mm_ss", CultureInfo.InvariantCulture);
+ this.sessionName = string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", executable, Environment.ProcessId, dateTimeNow);
+ this.etwFilePath = Path.Combine(etwFolderPath, $"{this.sessionName}.etl");
+
+ this.traceSession = new TraceEventSession(
+ this.sessionName, this.etwFilePath, (TraceEventSessionOptions)(TraceEventSessionOptions.Create | TraceEventSessionOptions.PrivateLogger | TraceEventSessionOptions.PrivateInProcLogger));
+ TraceEventProviderOptions args = new TraceEventProviderOptions();
+
+ this.traceSession.EnableProvider(
+ PowerToysTelemetry.Log.Guid,
+ matchAnyKeywords: (ulong)TelemetryKeyword | (ulong)MeasuresKeyword | (ulong)CriticalDataKeyword);
+
+ this.started = true;
+ }
+ }
+
+ ///
+ /// Stops the trace session.
+ ///
+ public void Stop()
+ {
+ lock (this)
+ {
+ if (!this.started)
+ {
+ return;
+ }
+
+ if (this.traceSession != null)
+ {
+ Trace.TraceInformation("Disposing EventTraceSession");
+ this.traceSession.Dispose();
+ this.traceSession = null;
+ this.started = false;
+ }
+ }
+ }
+
+ ///
+ /// Disposes the object.
+ ///
+ /// boolean for disposing.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!this.disposedValue)
+ {
+ if (disposing)
+ {
+ this.Stop();
+ }
+
+ this.disposedValue = true;
+ }
+ }
+ }
+}
diff --git a/src/common/ManagedTelemetry/Telemetry/ManagedTelemetry.csproj b/src/common/ManagedTelemetry/Telemetry/ManagedTelemetry.csproj
index a1280f1111..edd5595129 100644
--- a/src/common/ManagedTelemetry/Telemetry/ManagedTelemetry.csproj
+++ b/src/common/ManagedTelemetry/Telemetry/ManagedTelemetry.csproj
@@ -2,7 +2,7 @@
-
+
PowerToys Telemetry
PowerToys.ManagedTelemetry
@@ -12,4 +12,8 @@
+
+
+
+
diff --git a/src/common/ManagedTelemetry/Telemetry/PowerToysTelemetry.cs b/src/common/ManagedTelemetry/Telemetry/PowerToysTelemetry.cs
index 9b74c682df..c1b77e67e4 100644
--- a/src/common/ManagedTelemetry/Telemetry/PowerToysTelemetry.cs
+++ b/src/common/ManagedTelemetry/Telemetry/PowerToysTelemetry.cs
@@ -37,14 +37,17 @@ namespace Microsoft.PowerToys.Telemetry
public void WriteEvent(T telemetryEvent)
where T : EventBase, IEvent
{
- this.Write(
- telemetryEvent.EventName,
- new EventSourceOptions()
- {
- Keywords = ProjectKeywordMeasure,
- Tags = ProjectTelemetryTagProductAndServicePerformance,
- },
- telemetryEvent);
+ if (DataDiagnosticsSettings.GetEnabledValue())
+ {
+ this.Write(
+ telemetryEvent.EventName,
+ new EventSourceOptions()
+ {
+ Keywords = ProjectKeywordMeasure,
+ Tags = ProjectTelemetryTagProductAndServicePerformance,
+ },
+ telemetryEvent);
+ }
}
}
}
diff --git a/src/common/SettingsAPI/settings_helpers.cpp b/src/common/SettingsAPI/settings_helpers.cpp
index 974b2fff6a..25d9719a66 100644
--- a/src/common/SettingsAPI/settings_helpers.cpp
+++ b/src/common/SettingsAPI/settings_helpers.cpp
@@ -8,6 +8,8 @@ namespace PTSettingsHelper
constexpr inline const wchar_t* last_version_run_filename = L"last_version_run.json";
constexpr inline const wchar_t* opened_at_first_launch_json_field_name = L"openedAtFirstLaunch";
constexpr inline const wchar_t* last_version_json_field_name = L"last_version";
+ constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
+ constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
std::wstring get_root_save_folder_location()
{
@@ -25,7 +27,7 @@ namespace PTSettingsHelper
return result;
}
- std::wstring get_local_low_folder_location()
+ std::wstring get_local_low_folder_location()
{
PWSTR local_app_path;
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, NULL, &local_app_path));
@@ -112,7 +114,7 @@ namespace PTSettingsHelper
bool opened = saved_settings->GetNamedBoolean(opened_at_first_launch_json_field_name, false);
return opened;
}
-
+
return false;
}
@@ -124,12 +126,11 @@ namespace PTSettingsHelper
json::JsonObject obj;
obj.SetNamedValue(opened_at_first_launch_json_field_name, json::value(true));
- json::to_file(oobePath.c_str(), obj);
+ json::to_file(oobePath.c_str(), obj);
}
std::wstring get_last_version_run()
{
-
std::filesystem::path lastVersionRunPath(PTSettingsHelper::get_root_save_folder_location());
lastVersionRunPath = lastVersionRunPath.append(last_version_run_filename);
if (std::filesystem::exists(lastVersionRunPath))
@@ -157,4 +158,29 @@ namespace PTSettingsHelper
json::to_file(lastVersionRunPath.c_str(), obj);
}
+ void save_data_diagnostics(bool enabled)
+ {
+ HKEY key{};
+ if (RegCreateKeyExW(HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ 0,
+ nullptr,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ nullptr,
+ &key,
+ nullptr) != ERROR_SUCCESS)
+ {
+ return;
+ }
+
+ const bool value = enabled;
+ const size_t buf_size = sizeof(bool);
+ if (RegSetValueExW(key, DataDiagnosticsRegValueName, 0, REG_QWORD, reinterpret_cast(&value), buf_size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return;
+ }
+ RegCloseKey(key);
+ }
}
diff --git a/src/common/SettingsAPI/settings_helpers.h b/src/common/SettingsAPI/settings_helpers.h
index 9e01b3b206..14eae8ac62 100644
--- a/src/common/SettingsAPI/settings_helpers.h
+++ b/src/common/SettingsAPI/settings_helpers.h
@@ -24,4 +24,6 @@ namespace PTSettingsHelper
void save_oobe_opened_state();
std::wstring get_last_version_run();
void save_last_version_run(const std::wstring& version);
+
+ void save_data_diagnostics(bool enabled);
}
diff --git a/src/common/Telemetry/EtwTrace/EtwTrace.cpp b/src/common/Telemetry/EtwTrace/EtwTrace.cpp
new file mode 100644
index 0000000000..05b6956953
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/EtwTrace.cpp
@@ -0,0 +1,310 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+#pragma once
+#include "pch.h"
+
+#include "ETWTrace.h"
+
+#include
+
+#include
+#include
+
+namespace fs = std::filesystem;
+
+namespace
+{
+ constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
+ constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
+ constexpr inline const wchar_t* ViewDataDiagnosticsRegValueName = L"DataDiagnosticsViewEnabled";
+
+ inline std::wstring get_root_save_folder_location()
+ {
+ PWSTR local_app_path;
+ winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
+ std::wstring result{ local_app_path };
+ CoTaskMemFree(local_app_path);
+
+ result += L"\\Microsoft\\PowerToys";
+ std::filesystem::path save_path(result);
+ if (!std::filesystem::exists(save_path))
+ {
+ std::filesystem::create_directories(save_path);
+ }
+ return result;
+ }
+
+ bool IsDataDiagnosticsEnabled()
+ {
+ HKEY key{};
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ 0,
+ KEY_READ,
+ &key) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ DWORD isDataDiagnosticsEnabled = 0;
+ DWORD size = sizeof(isDataDiagnosticsEnabled);
+
+ if (RegGetValueW(
+ HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ DataDiagnosticsRegValueName,
+ RRF_RT_REG_DWORD,
+ nullptr,
+ &isDataDiagnosticsEnabled,
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return false;
+ }
+ RegCloseKey(key);
+
+ return isDataDiagnosticsEnabled;
+ }
+
+ bool isViewDataDiagnosticEnabled()
+ {
+ HKEY key{};
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ 0,
+ KEY_READ,
+ &key) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ DWORD isDataDiagnosticsEnabled = 0;
+ DWORD size = sizeof(isDataDiagnosticsEnabled);
+
+ if (RegGetValueW(
+ HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ ViewDataDiagnosticsRegValueName,
+ RRF_RT_REG_DWORD,
+ nullptr,
+ &isDataDiagnosticsEnabled,
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return false;
+ }
+ RegCloseKey(key);
+
+ return isDataDiagnosticsEnabled == 1;
+ }
+
+}
+
+namespace Shared
+{
+ namespace Trace
+ {
+ ETWTrace::ETWTrace()
+ {
+ GUID id;
+ if (SUCCEEDED(CLSIDFromString(PowerToysProviderGUID, &id)))
+ {
+ m_providerGUID = id;
+ }
+
+ fs::path outputFolder = get_root_save_folder_location();
+ m_etwFolder = (outputFolder / c_etwFolderName);
+ }
+
+ ETWTrace::ETWTrace(const std::wstring& etlFileNameOverride) :
+ ETWTrace()
+ {
+ m_etlFileNameOverride = etlFileNameOverride;
+ }
+
+ ETWTrace::~ETWTrace()
+ {
+ Flush();
+ Stop();
+ m_etwFolder.clear();
+ m_providerGUID = {};
+ }
+
+ void ETWTrace::UpdateState(bool tracing)
+ {
+ if (tracing)
+ {
+ Start();
+ }
+ else
+ {
+ Stop();
+ }
+ }
+
+ void ETWTrace::Flush()
+ {
+ if (m_tracing)
+ {
+ Control(EVENT_TRACE_CONTROL_FLUSH);
+ // Control(EVENT_TRACE_CONTROL_INCREMENT_FILE);
+ }
+ }
+
+ void ETWTrace::CreateEtwFolderIfNeeded()
+ {
+ if (!std::filesystem::exists(m_etwFolder))
+ {
+ std::filesystem::create_directories(m_etwFolder);
+ }
+ else if (!std::filesystem::is_directory(m_etwFolder))
+ {
+ std::filesystem::remove(m_etwFolder);
+ std::filesystem::create_directory(m_etwFolder);
+ }
+
+ THROW_HR_IF(E_UNEXPECTED, !std::filesystem::exists(m_etwFolder));
+ }
+
+ void ETWTrace::InitEventTraceProperties()
+ {
+ const std::filesystem::path exePath(wil::GetModuleFileNameW(nullptr));
+ const auto exeName = exePath.stem().wstring();
+
+ auto now = std::chrono::system_clock::now();
+ auto timeNow = std::chrono::system_clock::to_time_t(now);
+ std::wstringstream dateTime;
+ struct tm timeInfo
+ {
+ };
+ errno_t err = localtime_s(&timeInfo, &timeNow);
+ if (err == 0)
+ {
+ dateTime << std::put_time(&timeInfo, L"-%m-%d-%Y__%H_%M_%S");
+ }
+
+ if (m_etlFileNameOverride.empty())
+ {
+ m_sessionName = wil::str_printf(L"%ws-%d%ws", exeName.c_str(), GetCurrentProcessId(), dateTime.str().c_str());
+ }
+ else
+ {
+ m_sessionName = wil::str_printf(L"%ws-%d%ws", m_etlFileNameOverride.c_str(), GetCurrentProcessId(), dateTime.str().c_str());
+ }
+
+ std::replace(m_sessionName.begin(), m_sessionName.end(), '.', '_');
+
+ const ULONG etwSessionNameCharCount = static_cast(m_sessionName.size() + 1);
+ const ULONG etwSessionNameByteSize = etwSessionNameCharCount * sizeof(m_sessionName[0]);
+
+ auto etlFileNameFormattedCounter = m_sessionName + c_etwNewFileFormattedCounter;
+ std::filesystem::path etlFilePath = m_etwFolder / etlFileNameFormattedCounter;
+ etlFilePath.replace_extension(c_etwFileNameEnd);
+ THROW_HR_IF(E_UNEXPECTED, etlFilePath.empty());
+
+ const auto etlFilePathStr = etlFilePath.wstring();
+ // std::string/wstring returns number of characters not including the null terminator, so add +1 for that.
+ const ULONG etwFilePathCharCount = static_cast(etlFilePathStr.size() + 1);
+ const ULONG etwFilePathByteSize = etwFilePathCharCount * sizeof(etlFilePathStr[0]);
+
+ const ULONG bufferSizeInBytes = sizeof(EVENT_TRACE_PROPERTIES) + etwSessionNameByteSize + etwFilePathByteSize;
+ auto eventTracePropertiesBuffer = std::make_unique(bufferSizeInBytes);
+ ZeroMemory(eventTracePropertiesBuffer.get(), bufferSizeInBytes);
+ auto eventTraceProperties = reinterpret_cast(eventTracePropertiesBuffer.get());
+
+ eventTraceProperties->Wnode.BufferSize = bufferSizeInBytes;
+ eventTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
+ eventTraceProperties->Wnode.ClientContext = 1;
+ eventTraceProperties->Wnode.Guid = m_providerGUID;
+ eventTraceProperties->BufferSize = 4; // 4KB, the minimum size
+ eventTraceProperties->LogFileMode = EVENT_TRACE_PRIVATE_LOGGER_MODE | EVENT_TRACE_PRIVATE_IN_PROC | EVENT_TRACE_FILE_MODE_NEWFILE;
+ eventTraceProperties->MaximumFileSize = 1; // 1 MB
+
+ // LoggerName is placed at the end of EVENT_TRACE_PROPERTIES structure
+ eventTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
+ wcsncpy_s(reinterpret_cast(eventTracePropertiesBuffer.get() + eventTraceProperties->LoggerNameOffset), etwSessionNameCharCount, m_sessionName.c_str(), etwSessionNameCharCount);
+
+ // LogFileName is placed at the end of the Logger Name
+ eventTraceProperties->LogFileNameOffset = eventTraceProperties->LoggerNameOffset + etwSessionNameByteSize;
+ wcsncpy_s(reinterpret_cast(eventTracePropertiesBuffer.get() + eventTraceProperties->LogFileNameOffset), etwFilePathCharCount, etlFilePathStr.c_str(), etwFilePathCharCount);
+
+ m_eventTracePropertiesBuffer = std::move(eventTracePropertiesBuffer);
+ }
+
+ void ETWTrace::Start()
+ {
+ if (m_tracing)
+ {
+ return;
+ }
+
+ if (!IsDataDiagnosticsEnabled())
+ {
+ return;
+ }
+
+ if (!isViewDataDiagnosticEnabled())
+ {
+ return;
+ }
+
+ CreateEtwFolderIfNeeded();
+ InitEventTraceProperties();
+
+ auto eventTraceProperties = reinterpret_cast(m_eventTracePropertiesBuffer.get());
+ THROW_IF_WIN32_ERROR(StartTrace(&m_traceHandle, m_sessionName.c_str(), eventTraceProperties));
+ Enable(EVENT_CONTROL_CODE_ENABLE_PROVIDER);
+
+ m_tracing = true;
+
+ m_flushing_thread = std::thread([this] { FlushWorker(); });
+ }
+
+ void ETWTrace::Stop()
+ {
+ if (!m_tracing)
+ {
+ return;
+ }
+
+ Enable(EVENT_CONTROL_CODE_DISABLE_PROVIDER);
+
+ // ControlTrace with EVENT_TRACE_CONTROL_STOP on the trace handle,
+ // which is equivalent to calling CloseTrace() on the trace handle.
+ Control(EVENT_TRACE_CONTROL_STOP);
+
+ m_traceHandle = INVALID_PROCESSTRACE_HANDLE;
+ m_eventTracePropertiesBuffer.reset();
+ m_tracing = false;
+ m_terminate_flushing_thread.notify_one();
+ m_flushing_thread.join();
+ }
+
+ void ETWTrace::Control(ULONG traceControlCode)
+ {
+ auto eventTraceProperties = reinterpret_cast(m_eventTracePropertiesBuffer.get());
+ const ULONG result = ControlTrace(m_traceHandle, m_sessionName.c_str(), eventTraceProperties, traceControlCode);
+ THROW_IF_FAILED(HRESULT_FROM_WIN32(result));
+ }
+
+ void ETWTrace::Enable(ULONG eventControlCode)
+ {
+ // Control the main provider
+ THROW_IF_WIN32_ERROR(EnableTraceEx2(m_traceHandle, &m_providerGUID, eventControlCode, TRACE_LEVEL_VERBOSE, 0, 0, 0, nullptr));
+ }
+
+ void ETWTrace::FlushWorker()
+ {
+ std::unique_lock lock(m_mutex);
+ while (m_tracing)
+ {
+ m_terminate_flushing_thread.wait_for(lock,
+ std::chrono::seconds(30),
+ [this]() { return !m_tracing.load(); });
+ Flush();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/common/Telemetry/EtwTrace/EtwTrace.h b/src/common/Telemetry/EtwTrace/EtwTrace.h
new file mode 100644
index 0000000000..46b3e37c40
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/EtwTrace.h
@@ -0,0 +1,54 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+#pragma once
+#include "pch.h"
+
+#include
+#include
+#include
+#include
+
+namespace Shared
+{
+ namespace Trace
+ {
+ class ETWTrace
+ {
+ public:
+ static inline const wchar_t* PowerToysProviderGUID = L"{38e8889b-9731-53f5-e901-e8a7c1753074}";
+
+ ETWTrace();
+ ETWTrace(const std::wstring& etlFileNameOverride);
+ ~ETWTrace();
+
+ void UpdateState(bool tracing);
+ void Flush();
+
+ private:
+ void CreateEtwFolderIfNeeded();
+ void InitEventTraceProperties();
+ void Start();
+ void Stop();
+ void Control(const ULONG traceControlCode);
+ void Enable(const ULONG eventControlCode);
+ void FlushWorker();
+
+ GUID m_providerGUID{};
+ std::filesystem::path m_etwFolder;
+ std::wstring m_sessionName;
+ TRACEHANDLE m_traceHandle{ INVALID_PROCESSTRACE_HANDLE };
+ std::unique_ptr m_eventTracePropertiesBuffer;
+ std::atomic_bool m_tracing{ false };
+ std::wstring m_etlFileNameOverride{};
+ std::thread m_flushing_thread;
+ std::condition_variable m_terminate_flushing_thread;
+ std::mutex m_mutex;
+
+ static constexpr PCWSTR c_etwFolderName = L"etw";
+ static constexpr PCWSTR c_etwNewFileFormattedCounter = L"-%d";
+ static constexpr PCWSTR c_etwFileNameEnd = L".etl";
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj b/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj
new file mode 100644
index 0000000000..17b3be7a26
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj
@@ -0,0 +1,51 @@
+
+
+
+
+ 17.0
+ Win32Proj
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+ EtwTrace
+
+
+
+ StaticLibrary
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj.filters b/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj.filters
new file mode 100644
index 0000000000..9127669e77
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/EtwTrace.vcxproj.filters
@@ -0,0 +1,39 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/common/Telemetry/EtwTrace/packages.config b/src/common/Telemetry/EtwTrace/packages.config
new file mode 100644
index 0000000000..ff4b059648
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/common/Telemetry/EtwTrace/pch.cpp b/src/common/Telemetry/EtwTrace/pch.cpp
new file mode 100644
index 0000000000..64b7eef6d6
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/pch.cpp
@@ -0,0 +1,5 @@
+// pch.cpp: source file corresponding to the pre-compiled header
+
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
diff --git a/src/common/Telemetry/EtwTrace/pch.h b/src/common/Telemetry/EtwTrace/pch.h
new file mode 100644
index 0000000000..8db0e0c1e8
--- /dev/null
+++ b/src/common/Telemetry/EtwTrace/pch.h
@@ -0,0 +1,23 @@
+// pch.h: This is a precompiled header file.
+// Files listed below are compiled only once, improving build performance for future builds.
+// This also affects IntelliSense performance, including code completion and many code browsing features.
+// However, files listed here are ALL re-compiled if any one of them is updated between builds.
+// Do not add files here that you will be updating frequently as this negates the performance advantage.
+
+#ifndef PCH_H
+#define PCH_H
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#endif //PCH_H
diff --git a/src/common/Telemetry/TraceBase.h b/src/common/Telemetry/TraceBase.h
new file mode 100644
index 0000000000..da722bb457
--- /dev/null
+++ b/src/common/Telemetry/TraceBase.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "ProjectTelemetry.h"
+
+#define TraceLoggingWriteWrapper(provider, eventName, ...) \
+ if (IsDataDiagnosticsEnabled()) \
+ { \
+ TraceLoggingWrite(provider, eventName, __VA_ARGS__); \
+ }
+
+namespace telemetry
+{
+
+constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
+constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
+
+class TraceBase
+{
+public:
+ static void RegisterProvider()
+ {
+ TraceLoggingRegister(g_hProvider);
+ }
+
+ static void UnregisterProvider()
+ {
+ TraceLoggingUnregister(g_hProvider);
+ }
+
+ static bool IsDataDiagnosticsEnabled()
+ {
+ HKEY key{};
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ 0,
+ KEY_READ,
+ &key) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ DWORD isDataDiagnosticsEnabled = 0;
+ DWORD size = sizeof(isDataDiagnosticsEnabled);
+
+ if (RegGetValueW(
+ HKEY_CURRENT_USER,
+ DataDiagnosticsRegKey,
+ DataDiagnosticsRegValueName,
+ RRF_RT_REG_DWORD,
+ nullptr,
+ &isDataDiagnosticsEnabled,
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(key);
+ return false;
+ }
+ RegCloseKey(key);
+
+ return isDataDiagnosticsEnabled;
+ }
+};
+
+} // namespace telemetry
\ No newline at end of file
diff --git a/src/common/interop/Constants.cpp b/src/common/interop/Constants.cpp
index dc4641822b..144fb728ce 100644
--- a/src/common/interop/Constants.cpp
+++ b/src/common/interop/Constants.cpp
@@ -51,6 +51,10 @@ namespace winrt::PowerToys::Interop::implementation
{
return CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT;
}
+ hstring Constants::TerminateColorPickerSharedEvent()
+ {
+ return CommonSharedConstants::TERMINATE_COLOR_PICKER_SHARED_EVENT;
+ }
hstring Constants::AdvancedPasteShowUIMessage()
{
return CommonSharedConstants::ADVANCED_PASTE_SHOW_UI_MESSAGE;
@@ -63,18 +67,34 @@ namespace winrt::PowerToys::Interop::implementation
{
return CommonSharedConstants::ADVANCED_PASTE_JSON_MESSAGE;
}
+ hstring Constants::AdvancedPasteAdditionalActionMessage()
+ {
+ return CommonSharedConstants::ADVANCED_PASTE_ADDITIONAL_ACTION_MESSAGE;
+ }
hstring Constants::AdvancedPasteCustomActionMessage()
{
return CommonSharedConstants::ADVANCED_PASTE_CUSTOM_ACTION_MESSAGE;
}
+ hstring Constants::AdvancedPasteTerminateAppMessage()
+ {
+ return CommonSharedConstants::ADVANCED_PASTE_TERMINATE_APP_MESSAGE;
+ }
hstring Constants::ShowPowerOCRSharedEvent()
{
return CommonSharedConstants::SHOW_POWEROCR_SHARED_EVENT;
}
+ hstring Constants::TerminatePowerOCRSharedEvent()
+ {
+ return CommonSharedConstants::TERMINATE_POWEROCR_SHARED_EVENT;
+ }
hstring Constants::MouseJumpShowPreviewEvent()
{
return CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT;
}
+ hstring Constants::TerminateMouseJumpSharedEvent()
+ {
+ return CommonSharedConstants::TERMINATE_MOUSE_JUMP_SHARED_EVENT;
+ }
hstring Constants::AwakeExitEvent()
{
return CommonSharedConstants::AWAKE_EXIT_EVENT;
@@ -83,6 +103,10 @@ namespace winrt::PowerToys::Interop::implementation
{
return CommonSharedConstants::SHOW_PEEK_SHARED_EVENT;
}
+ hstring Constants::TerminatePeekEvent()
+ {
+ return CommonSharedConstants::TERMINATE_PEEK_SHARED_EVENT;
+ }
hstring Constants::PowerAccentExitEvent()
{
return CommonSharedConstants::POWERACCENT_EXIT_EVENT;
@@ -131,6 +155,10 @@ namespace winrt::PowerToys::Interop::implementation
{
return CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT;
}
+ hstring Constants::TerminateHostsSharedEvent()
+ {
+ return CommonSharedConstants::TERMINATE_HOSTS_EVENT;
+ }
hstring Constants::CropAndLockThumbnailEvent()
{
return CommonSharedConstants::CROP_AND_LOCK_THUMBNAIL_EVENT;
@@ -155,4 +183,8 @@ namespace winrt::PowerToys::Interop::implementation
{
return CommonSharedConstants::WORKSPACES_HOTKEY_EVENT;
}
+ hstring Constants::PowerToysRunnerTerminateSettingsEvent()
+ {
+ return CommonSharedConstants::TERMINATE_SETTINGS_SHARED_EVENT;
+ }
}
diff --git a/src/common/interop/Constants.h b/src/common/interop/Constants.h
index b59cd3e62c..b2a5fdef53 100644
--- a/src/common/interop/Constants.h
+++ b/src/common/interop/Constants.h
@@ -16,14 +16,20 @@ namespace winrt::PowerToys::Interop::implementation
static hstring FZEToggleEvent();
static hstring ColorPickerSendSettingsTelemetryEvent();
static hstring ShowColorPickerSharedEvent();
+ static hstring TerminateColorPickerSharedEvent();
static hstring AdvancedPasteShowUIMessage();
static hstring AdvancedPasteMarkdownMessage();
static hstring AdvancedPasteJsonMessage();
+ static hstring AdvancedPasteAdditionalActionMessage();
static hstring AdvancedPasteCustomActionMessage();
+ static hstring AdvancedPasteTerminateAppMessage();
static hstring ShowPowerOCRSharedEvent();
+ static hstring TerminatePowerOCRSharedEvent();
static hstring MouseJumpShowPreviewEvent();
+ static hstring TerminateMouseJumpSharedEvent();
static hstring AwakeExitEvent();
static hstring ShowPeekEvent();
+ static hstring TerminatePeekEvent();
static hstring PowerAccentExitEvent();
static hstring ShortcutGuideTriggerEvent();
static hstring RegistryPreviewTriggerEvent();
@@ -36,12 +42,14 @@ namespace winrt::PowerToys::Interop::implementation
static hstring SvgPreviewResizeEvent();
static hstring ShowHostsSharedEvent();
static hstring ShowHostsAdminSharedEvent();
+ static hstring TerminateHostsSharedEvent();
static hstring CropAndLockThumbnailEvent();
static hstring CropAndLockReparentEvent();
static hstring ShowEnvironmentVariablesSharedEvent();
static hstring ShowEnvironmentVariablesAdminSharedEvent();
static hstring WorkspacesLaunchEditorEvent();
static hstring WorkspacesHotkeyEvent();
+ static hstring PowerToysRunnerTerminateSettingsEvent();
};
}
diff --git a/src/common/interop/Constants.idl b/src/common/interop/Constants.idl
index a681ee5a81..e2a356d5ef 100644
--- a/src/common/interop/Constants.idl
+++ b/src/common/interop/Constants.idl
@@ -13,14 +13,20 @@ namespace PowerToys
static String FZEToggleEvent();
static String ColorPickerSendSettingsTelemetryEvent();
static String ShowColorPickerSharedEvent();
+ static String TerminateColorPickerSharedEvent();
static String AdvancedPasteShowUIMessage();
static String AdvancedPasteMarkdownMessage();
static String AdvancedPasteJsonMessage();
+ static String AdvancedPasteAdditionalActionMessage();
static String AdvancedPasteCustomActionMessage();
+ static String AdvancedPasteTerminateAppMessage();
static String ShowPowerOCRSharedEvent();
+ static String TerminatePowerOCRSharedEvent();
static String MouseJumpShowPreviewEvent();
+ static String TerminateMouseJumpSharedEvent();
static String AwakeExitEvent();
static String ShowPeekEvent();
+ static String TerminatePeekEvent();
static String PowerAccentExitEvent();
static String ShortcutGuideTriggerEvent();
static String RegistryPreviewTriggerEvent();
@@ -33,12 +39,14 @@ namespace PowerToys
static String SvgPreviewResizeEvent();
static String ShowHostsSharedEvent();
static String ShowHostsAdminSharedEvent();
+ static String TerminateHostsSharedEvent();
static String CropAndLockThumbnailEvent();
static String CropAndLockReparentEvent();
static String ShowEnvironmentVariablesSharedEvent();
static String ShowEnvironmentVariablesAdminSharedEvent();
static String WorkspacesLaunchEditorEvent();
static String WorkspacesHotkeyEvent();
+ static String PowerToysRunnerTerminateSettingsEvent();
}
}
}
\ No newline at end of file
diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h
index f29d8b720f..c031d5d336 100644
--- a/src/common/interop/shared_constants.h
+++ b/src/common/interop/shared_constants.h
@@ -12,6 +12,9 @@ namespace CommonSharedConstants
const wchar_t APPDATA_PATH[] = L"Microsoft\\PowerToys";
+ // Path to the event used by runner to terminate Settings app
+ const wchar_t TERMINATE_SETTINGS_SHARED_EVENT[] = L"Local\\PowerToysRunnerTerminateSettingsEvent-c34cb661-2e69-4613-a1f8-4e39c25d7ef6";
+
// Path to the event used by PowerLauncher
const wchar_t POWER_LAUNCHER_SHARED_EVENT[] = L"Local\\PowerToysRunInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab";
@@ -32,11 +35,17 @@ namespace CommonSharedConstants
const wchar_t ADVANCED_PASTE_JSON_MESSAGE[] = L"PasteJson";
+ const wchar_t ADVANCED_PASTE_ADDITIONAL_ACTION_MESSAGE[] = L"AdditionalAction";
+
const wchar_t ADVANCED_PASTE_CUSTOM_ACTION_MESSAGE[] = L"CustomAction";
+ const wchar_t ADVANCED_PASTE_TERMINATE_APP_MESSAGE[] = L"TerminateApp";
+
// Path to the event used to show Color Picker
const wchar_t SHOW_COLOR_PICKER_SHARED_EVENT[] = L"Local\\ShowColorPickerEvent-8c46be2a-3e05-4186-b56b-4ae986ef2525";
+ const wchar_t TERMINATE_COLOR_PICKER_SHARED_EVENT[] = L"Local\\TerminateColorPickerEvent-3d676258-c4d5-424e-a87a-4be22020e813";
+
const wchar_t SHORTCUT_GUIDE_TRIGGER_EVENT[] = L"Local\\ShortcutGuide-TriggerEvent-d4275ad3-2531-4d19-9252-c0becbd9b496";
const wchar_t SHORTCUT_GUIDE_EXIT_EVENT[] = L"Local\\ShortcutGuide-ExitEvent-35697cdd-a3d2-47d6-a246-34efcc73eac0";
@@ -51,21 +60,29 @@ namespace CommonSharedConstants
const wchar_t SHOW_HOSTS_ADMIN_EVENT[] = L"Local\\Hosts-ShowHostsAdminEvent-60ff44e2-efd3-43bf-928a-f4d269f98bec";
+ const wchar_t TERMINATE_HOSTS_EVENT[] = L"Local\\Hosts-TerminateHostsEvent-d5410d5e-45a6-4d11-bbf0-a4ec2d064888";
+
// Path to the event used by Awake
const wchar_t AWAKE_EXIT_EVENT[] = L"Local\\PowerToysAwakeExitEvent-c0d5e305-35fc-4fb5-83ec-f6070cfaf7fe";
// Path to the event used by AlwaysOnTop
const wchar_t ALWAYS_ON_TOP_PIN_EVENT[] = L"Local\\AlwaysOnTopPinEvent-892e0aa2-cfa8-4cc4-b196-ddeb32314ce8";
+ const wchar_t ALWAYS_ON_TOP_TERMINATE_EVENT[] = L"Local\\AlwaysOnTopTerminateEvent-cfdf1eae-791f-4953-8021-2f18f3837eae";
+
// Path to the event used by PowerAccent
const wchar_t POWERACCENT_EXIT_EVENT[] = L"Local\\PowerToysPowerAccentExitEvent-53e93389-d19a-4fbb-9b36-1981c8965e17";
// Path to the event used by PowerOCR
const wchar_t SHOW_POWEROCR_SHARED_EVENT[] = L"Local\\PowerOCREvent-dc864e06-e1af-4ecc-9078-f98bee745e3a";
+ const wchar_t TERMINATE_POWEROCR_SHARED_EVENT[] = L"Local\\TerminatePowerOCREvent-08e5de9d-15df-4ea8-8840-487c13435a67";
+
// Path to the events used by Mouse Jump
const wchar_t MOUSE_JUMP_SHOW_PREVIEW_EVENT[] = L"Local\\MouseJumpEvent-aa0be051-3396-4976-b7ba-1a9cc7d236a5";
+ const wchar_t TERMINATE_MOUSE_JUMP_SHARED_EVENT[] = L"Local\\TerminateMouseJumpEvent-252fa337-317f-4c37-a61f-99464c3f9728";
+
// Path to the event used by RegistryPreview
const wchar_t REGISTRY_PREVIEW_TRIGGER_EVENT[] = L"Local\\RegistryPreviewEvent-4C559468-F75A-4E7F-BC4F-9C9688316687";
@@ -95,6 +112,11 @@ namespace CommonSharedConstants
// Path to the event used to show Peek
const wchar_t SHOW_PEEK_SHARED_EVENT[] = L"Local\\ShowPeekEvent";
+ // Path to the event used to terminate Peek
+ const wchar_t TERMINATE_PEEK_SHARED_EVENT[] = L"Local\\TerminatePeekEvent-267149fe-7ed2-427d-a3ad-9e18203c037c";
+
+ // Path to the event used to terminate KBM
+ const wchar_t TERMINATE_KBM_SHARED_EVENT[] = L"Local\\TerminateKBMSharedEvent-a787c967-55b6-47de-94d9-56f39fed839e";
// Path to the events used by CropAndLock
const wchar_t CROP_AND_LOCK_REPARENT_EVENT[] = L"Local\\PowerToysCropAndLockReparentEvent-6060860a-76a1-44e8-8d0e-6355785e9c36";
diff --git a/src/common/utils/EventWaiter.h b/src/common/utils/EventWaiter.h
index 304f475ade..1a2ba89f02 100644
--- a/src/common/utils/EventWaiter.h
+++ b/src/common/utils/EventWaiter.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include
#include
#include
diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h
index 66da6148f2..886c468222 100644
--- a/src/common/utils/gpo.h
+++ b/src/common/utils/gpo.h
@@ -73,6 +73,7 @@ namespace powertoys_gpo {
// The registry value names for other PowerToys policies.
const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
+ const std::wstring POLICY_ALLOW_DATA_DIAGNOSTICS = L"AllowDataDiagnostics";
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState";
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS = L"AllowPowerToysAdvancedPasteOnlineAIModels";
const std::wstring POLICY_MWB_CLIPBOARD_SHARING_ENABLED = L"MwbClipboardSharingEnabled";
@@ -493,6 +494,11 @@ namespace powertoys_gpo {
return getConfiguredValue(POLICY_ALLOW_EXPERIMENTATION);
}
+ inline gpo_rule_configured_t getAllowDataDiagnosticsValue()
+ {
+ return getConfiguredValue(POLICY_ALLOW_DATA_DIAGNOSTICS);
+ }
+
inline gpo_rule_configured_t getRunPluginEnabledValue(std::string pluginID)
{
if (pluginID == "" || pluginID == " ")
diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx
index 9ae865ab93..36f4231ce6 100644
--- a/src/gpo/assets/PowerToys.admx
+++ b/src/gpo/assets/PowerToys.admx
@@ -5,7 +5,7 @@
-
+
@@ -520,6 +520,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml
index b549b4d962..e34851702e 100644
--- a/src/gpo/assets/en-US/PowerToys.adml
+++ b/src/gpo/assets/en-US/PowerToys.adml
@@ -1,7 +1,7 @@
-
+
PowerToys
PowerToys
@@ -102,6 +102,12 @@ If disabled or not configured, the user can control this in the settings of Powe
If this setting is enabled or not configured, the user can control experimentation in the PowerToys settings menu.
If this setting is disabled, experimentation is not allowed.
+
+ This policy configures whether sending of PowerToys diagnostic data is allowed. With diagnostic data sending allowed the user helps inform bug fixes, performance and improvements.
+
+If this setting is enabled or not configured, the user can control diagnostic data sending in the PowerToys settings menu.
+
+If this setting is disabled, diagnostic data sending is not allowed.
This policy configures the enabled state for all PowerToys Run plugins. All plugins will have the same state.
@@ -260,6 +266,7 @@ If you don't configure this policy, the user takes control over the setting and
Disable user defined IP Address mapping rules
Predefined IP Address mapping rules
Hide template filename extension
+ Allow sending diagnostic data
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj
index ca34cf03ff..c8ea965a4d 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj
@@ -54,12 +54,15 @@
+
+
+
+
-
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/App.xaml.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/App.xaml.cs
index 3f990ef6fa..3595276c5d 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/App.xaml.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/App.xaml.cs
@@ -3,17 +3,22 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
+using AdvancedPaste.Models;
+using AdvancedPaste.Services;
using AdvancedPaste.Settings;
using AdvancedPaste.ViewModels;
using ManagedCommon;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Windows.Graphics;
@@ -34,6 +39,15 @@ namespace AdvancedPaste
{
public IHost Host { get; private set; }
+ public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
+
+ private static readonly Dictionary AdditionalActionIPCKeys =
+ typeof(PasteFormats).GetFields()
+ .Where(field => field.IsLiteral)
+ .Select(field => (Format: (PasteFormats)field.GetRawConstantValue(), field.GetCustomAttribute().IPCKey))
+ .Where(field => field.IPCKey != null)
+ .ToDictionary(field => field.IPCKey, field => field.Format);
+
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
private readonly OptionsViewModel viewModel;
@@ -60,8 +74,10 @@ namespace AdvancedPaste
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder().UseContentRoot(AppContext.BaseDirectory).ConfigureServices((context, services) =>
{
- services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
}).Build();
viewModel = GetService();
@@ -98,7 +114,11 @@ namespace AdvancedPaste
{
RunnerHelper.WaitForPowerToysRunner(powerToysRunnerPid, () =>
{
- Environment.Exit(0);
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ Dispose();
+ Environment.Exit(0);
+ });
});
}
}
@@ -111,35 +131,40 @@ namespace AdvancedPaste
private void ProcessNamedPipe(string pipeName)
{
- void OnMessage(string message) => _dispatcherQueue.TryEnqueue(() => OnNamedPipeMessage(message));
+ void OnMessage(string message) => _dispatcherQueue.TryEnqueue(async () => await OnNamedPipeMessage(message));
- Task.Run(async () =>
- {
- var connectTimeout = TimeSpan.FromSeconds(10);
- await NamedPipeProcessor.ProcessNamedPipeAsync(pipeName, connectTimeout, OnMessage, CancellationToken.None);
- });
+ Task.Run(async () => await NamedPipeProcessor.ProcessNamedPipeAsync(pipeName, connectTimeout: TimeSpan.FromSeconds(10), OnMessage, CancellationToken.None));
}
- private void OnNamedPipeMessage(string message)
+ private async Task OnNamedPipeMessage(string message)
{
var messageParts = message.Split();
var messageType = messageParts.First();
if (messageType == PowerToys.Interop.Constants.AdvancedPasteShowUIMessage())
{
- OnAdvancedPasteHotkey();
+ await ShowWindow();
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteMarkdownMessage())
{
- OnAdvancedPasteMarkdownHotkey();
+ await viewModel.ExecutePasteFormatAsync(PasteFormats.Markdown, PasteActionSource.GlobalKeyboardShortcut);
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteJsonMessage())
{
- OnAdvancedPasteJsonHotkey();
+ await viewModel.ExecutePasteFormatAsync(PasteFormats.Json, PasteActionSource.GlobalKeyboardShortcut);
+ }
+ else if (messageType == PowerToys.Interop.Constants.AdvancedPasteAdditionalActionMessage())
+ {
+ await OnAdvancedPasteAdditionalActionHotkey(messageParts);
}
else if (messageType == PowerToys.Interop.Constants.AdvancedPasteCustomActionMessage())
{
- OnAdvancedPasteCustomActionHotkey(messageParts);
+ await OnAdvancedPasteCustomActionHotkey(messageParts);
+ }
+ else if (messageType == PowerToys.Interop.Constants.AdvancedPasteTerminateAppMessage())
+ {
+ Dispose();
+ Environment.Exit(0);
}
}
@@ -148,24 +173,27 @@ namespace AdvancedPaste
Logger.LogError("Unhandled exception", e.Exception);
}
- private void OnAdvancedPasteJsonHotkey()
+ private async Task OnAdvancedPasteAdditionalActionHotkey(string[] messageParts)
{
- viewModel.ReadClipboard();
- viewModel.ToJsonFunction(true);
+ if (messageParts.Length != 2)
+ {
+ Logger.LogWarning("Unexpected additional action message");
+ }
+ else
+ {
+ if (!AdditionalActionIPCKeys.TryGetValue(messageParts[1], out PasteFormats pasteFormat))
+ {
+ Logger.LogWarning($"Unexpected additional action type {messageParts[1]}");
+ }
+ else
+ {
+ await ShowWindow();
+ await viewModel.ExecutePasteFormatAsync(pasteFormat, PasteActionSource.GlobalKeyboardShortcut);
+ }
+ }
}
- private void OnAdvancedPasteMarkdownHotkey()
- {
- viewModel.ReadClipboard();
- viewModel.ToMarkdownFunction(true);
- }
-
- private void OnAdvancedPasteHotkey()
- {
- ShowWindow();
- }
-
- private void OnAdvancedPasteCustomActionHotkey(string[] messageParts)
+ private async Task OnAdvancedPasteCustomActionHotkey(string[] messageParts)
{
if (messageParts.Length != 2)
{
@@ -179,16 +207,15 @@ namespace AdvancedPaste
}
else
{
- ShowWindow();
- viewModel.ReadClipboard();
- viewModel.ExecuteCustomActionWithPaste(customActionId);
+ await ShowWindow();
+ await viewModel.ExecuteCustomActionAsync(customActionId, PasteActionSource.GlobalKeyboardShortcut);
}
}
}
- private void ShowWindow()
+ private async Task ShowWindow()
{
- viewModel.OnShow();
+ await viewModel.OnShowAsync();
if (window is null)
{
@@ -229,6 +256,7 @@ namespace AdvancedPaste
{
if (disposing)
{
+ EtwTrace?.Dispose();
window.Dispose();
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml
index 27891312ac..2c0d9ea937 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml
@@ -346,7 +346,7 @@
x:Name="InputTxtBox"
HorizontalAlignment="Stretch"
x:FieldModifier="public"
- IsEnabled="{x:Bind ViewModel.IsClipboardDataText, Mode=OneWay}"
+ IsEnabled="{x:Bind ViewModel.ClipboardHasData, Mode=OneWay}"
KeyDown="InputTxtBox_KeyDown"
PlaceholderText="{x:Bind ViewModel.InputTxtBoxPlaceholderText, Mode=OneWay}"
Style="{StaticResource CustomTextBoxStyle}"
@@ -589,7 +589,7 @@
Background="Transparent"
Visibility="{x:Bind ViewModel.IsCustomAIEnabled, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
-
+
@@ -638,7 +638,7 @@
FontWeight="SemiBold"
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
- Text="{x:Bind ViewModel.ApiErrorText, Mode=OneWay}" />
+ Text="{x:Bind ViewModel.PasteOperationErrorText, Mode=OneWay}" />
();
+ InitializeComponent();
ViewModel = App.GetService();
- ViewModel.CustomActionActivated += (_, e) => GenerateCustom(e.ForcePasteCustom);
+ ViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ ViewModel.CustomActionActivated += ViewModel_CustomActionActivated;
+ }
+
+ private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(ViewModel.Busy) || e.PropertyName == nameof(ViewModel.PasteOperationErrorText))
+ {
+ var state = ViewModel.Busy ? "LoadingState" : string.IsNullOrEmpty(ViewModel.PasteOperationErrorText) ? "DefaultState" : "ErrorState";
+ VisualStateManager.GoToState(this, state, true);
+ }
+ }
+
+ private void ViewModel_CustomActionActivated(object sender, CustomActionActivatedEventArgs e)
+ {
+ Logger.LogTrace();
+
+ if (!e.PasteResult)
+ {
+ PreviewGrid.Width = InputTxtBox.ActualWidth;
+ PreviewFlyout.ShowAt(InputTxtBox);
+ }
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
@@ -68,48 +79,7 @@ namespace AdvancedPaste.Controls
}
[RelayCommand]
- private void GenerateCustom() => GenerateCustom(false);
-
- private void GenerateCustom(bool forcePasteCustom)
- {
- Logger.LogTrace();
-
- VisualStateManager.GoToState(this, "LoadingState", true);
- string inputInstructions = ViewModel.Query;
- ViewModel.SaveQuery(inputInstructions);
-
- var customFormatTask = ViewModel.GenerateCustomFunction(inputInstructions);
- var delayTask = forcePasteCustom ? Task.Delay(MinTaskTime) : Task.CompletedTask;
- Task.WhenAll(customFormatTask, delayTask)
- .ContinueWith(
- _ =>
- {
- _dispatcherQueue.TryEnqueue(() =>
- {
- ViewModel.CustomFormatResult = customFormatTask.Result;
-
- if (ViewModel.ApiRequestStatus == (int)HttpStatusCode.OK)
- {
- VisualStateManager.GoToState(this, "DefaultState", true);
- if (_userSettings.ShowCustomPreview && !forcePasteCustom)
- {
- PreviewGrid.Width = InputTxtBox.ActualWidth;
- PreviewFlyout.ShowAt(InputTxtBox);
- }
- else
- {
- ViewModel.PasteCustom();
- InputTxtBox.Text = string.Empty;
- }
- }
- else
- {
- VisualStateManager.GoToState(this, "ErrorState", true);
- }
- });
- },
- TaskScheduler.Default);
- }
+ private async Task GenerateCustomAsync() => await ViewModel.GenerateCustomFunctionAsync(PasteActionSource.PromptBox);
[RelayCommand]
private void Recall()
@@ -127,29 +97,24 @@ namespace AdvancedPaste.Controls
ClipboardHelper.SetClipboardTextContent(lastQuery.ClipboardData);
}
- private void InputTxtBox_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
+ private async void InputTxtBox_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && InputTxtBox.Text.Length > 0 && ViewModel.IsCustomAIEnabled)
{
- GenerateCustom();
+ await GenerateCustomAsync();
}
}
private void PreviewPasteBtn_Click(object sender, RoutedEventArgs e)
{
ViewModel.PasteCustom();
- InputTxtBox.Text = string.Empty;
}
private void ThumbUpDown_Click(object sender, RoutedEventArgs e)
{
- if (sender is Button btn)
+ if (sender is Button btn && bool.TryParse(btn.CommandParameter as string, out bool result))
{
- bool result;
- if (bool.TryParse(btn.CommandParameter as string, out result))
- {
- PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteCustomFormatOutputThumbUpDownEvent(result));
- }
+ PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteCustomFormatOutputThumbUpDownEvent(result));
}
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/PasteFormatsToHeightConverter.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/PasteFormatsToHeightConverter.cs
new file mode 100644
index 0000000000..2061bdefc9
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/PasteFormatsToHeightConverter.cs
@@ -0,0 +1,24 @@
+// 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;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Data;
+
+namespace AdvancedPaste.Converters;
+
+public sealed partial class PasteFormatsToHeightConverter : IValueConverter
+{
+ private const int ItemHeight = 40;
+
+ public int MaxItems { get; set; } = 5;
+
+ public object Convert(object value, Type targetType, object parameter, string language) =>
+ new GridLength(GetHeight((value is ICollection collection) ? collection.Count : (value is int intValue) ? intValue : 0));
+
+ public int GetHeight(int itemCount) => Math.Min(MaxItems, itemCount) * ItemHeight;
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml
index 8aa111219c..33a0dec49f 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml
@@ -8,9 +8,9 @@
xmlns:pages="using:AdvancedPaste.Pages"
xmlns:winuiex="using:WinUIEx"
Width="420"
- Height="308"
+ Height="188"
MinWidth="420"
- MinHeight="308"
+ MinHeight="188"
Closed="WindowEx_Closed"
IsAlwaysOnTop="True"
IsMaximizable="False"
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs
index 314e503ed8..6536bcfed9 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs
@@ -4,10 +4,15 @@
using System;
+using System.Linq;
+using AdvancedPaste.Converters;
using AdvancedPaste.Helpers;
+using AdvancedPaste.Models;
using AdvancedPaste.Settings;
using AdvancedPaste.ViewModels;
+
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using WinUIEx;
@@ -24,25 +29,32 @@ namespace AdvancedPaste
public MainWindow()
{
- this.InitializeComponent();
+ InitializeComponent();
_userSettings = App.GetService();
+
var optionsViewModel = App.GetService();
var baseHeight = MinHeight;
+ var coreActionCount = PasteFormat.MetadataDict.Values.Count(metadata => metadata.IsCoreAction);
void UpdateHeight()
{
- var trimmedCustomActionCount = optionsViewModel.IsPasteWithAIEnabled ? Math.Min(_userSettings.CustomActions.Count, 5) : 0;
- Height = MinHeight = baseHeight + (trimmedCustomActionCount * 40);
+ double GetHeight(int maxCustomActionCount) =>
+ baseHeight +
+ new PasteFormatsToHeightConverter().GetHeight(coreActionCount + _userSettings.AdditionalActions.Count) +
+ new PasteFormatsToHeightConverter() { MaxItems = maxCustomActionCount }.GetHeight(optionsViewModel.IsAIServiceEnabled ? _userSettings.CustomActions.Count : 0);
+
+ MinHeight = GetHeight(1);
+ Height = GetHeight(5);
}
UpdateHeight();
- _userSettings.CustomActions.CollectionChanged += (_, _) => UpdateHeight();
+ _userSettings.Changed += (_, _) => UpdateHeight();
optionsViewModel.PropertyChanged += (_, e) =>
{
- if (e.PropertyName == nameof(optionsViewModel.IsPasteWithAIEnabled))
+ if (e.PropertyName == nameof(optionsViewModel.IsAIServiceEnabled))
{
UpdateHeight();
}
@@ -85,6 +97,7 @@ namespace AdvancedPaste
if (!_disposedValue)
{
_msgMonitor?.Dispose();
+ (Application.Current as App).EtwTrace?.Dispose();
_disposedValue = true;
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml
index f45a222866..b4e99ebaed 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml
@@ -16,8 +16,9 @@
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -166,9 +186,9 @@
BorderThickness="0,1,0,0"
RowSpacing="4">
+
-
-
+
@@ -176,12 +196,13 @@
x:Name="PasteOptionsListView"
Grid.Row="0"
VerticalAlignment="Bottom"
- IsEnabled="{x:Bind ViewModel.IsClipboardDataText, Mode=OneWay}"
- IsItemClickEnabled="True"
- ItemClick="ListView_Click"
+ IsItemClickEnabled="False"
+ ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}"
ItemContainerTransitions="{x:Null}"
ItemTemplate="{StaticResource PasteFormatTemplate}"
ItemsSource="{x:Bind ViewModel.StandardPasteFormats, Mode=OneWay}"
+ ScrollViewer.VerticalScrollBarVisibility="Visible"
+ ScrollViewer.VerticalScrollMode="Auto"
SelectionMode="None"
TabIndex="1" />
@@ -196,9 +217,8 @@
x:Name="CustomActionsListView"
Grid.Row="2"
VerticalAlignment="Top"
- IsEnabled="{x:Bind ViewModel.IsCustomAIEnabled, Mode=OneWay}"
- IsItemClickEnabled="True"
- ItemClick="ListView_Click"
+ IsItemClickEnabled="False"
+ ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}"
ItemContainerTransitions="{x:Null}"
ItemTemplate="{StaticResource PasteFormatTemplate}"
ItemsSource="{x:Bind ViewModel.CustomActionPasteFormats, Mode=OneWay}"
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml.cs
index ab25db1d7c..d3e4ff1829 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml.cs
@@ -130,15 +130,15 @@ namespace AdvancedPaste.Pages
}
}
- private void ListView_Click(object sender, ItemClickEventArgs e)
+ private async void ListView_Button_Click(object sender, RoutedEventArgs e)
{
- if (e.ClickedItem is PasteFormat format)
+ if (sender is Button { DataContext: PasteFormat format })
{
- ViewModel.ExecutePasteFormat(format);
+ await ViewModel.ExecutePasteFormatAsync(format, PasteActionSource.ContextMenu);
}
}
- private void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAccelerator sender, Microsoft.UI.Xaml.Input.KeyboardAcceleratorInvokedEventArgs args)
+ private async void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAccelerator sender, Microsoft.UI.Xaml.Input.KeyboardAcceleratorInvokedEventArgs args)
{
if (GetMainWindow()?.Visible is false)
{
@@ -171,7 +171,7 @@ namespace AdvancedPaste.Pages
case VirtualKey.Number7:
case VirtualKey.Number8:
case VirtualKey.Number9:
- ViewModel.ExecutePasteFormat(sender.Key);
+ await ViewModel.ExecutePasteFormatAsync(sender.Key);
break;
default:
@@ -199,8 +199,7 @@ namespace AdvancedPaste.Pages
}
else if (item.Image is not null)
{
- RandomAccessStreamReference image = null;
- image = await item.Item.Content.GetBitmapAsync();
+ RandomAccessStreamReference image = await item.Item.Content.GetBitmapAsync();
ClipboardHelper.SetClipboardImageContent(image);
}
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardHelper.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardHelper.cs
index 4c1bf5b24e..9ec1dd1618 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardHelper.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardHelper.cs
@@ -3,12 +3,16 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Threading;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
+using AdvancedPaste.Models;
using ManagedCommon;
-using Microsoft.UI.Xaml.Media.Imaging;
using Windows.ApplicationModel.DataTransfer;
+using Windows.Data.Html;
+using Windows.Graphics.Imaging;
+using Windows.Storage;
using Windows.Storage.Streams;
using Windows.System;
@@ -16,6 +20,34 @@ namespace AdvancedPaste.Helpers
{
internal static class ClipboardHelper
{
+ private static readonly HashSet ImageFileTypes = new(StringComparer.InvariantCultureIgnoreCase) { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico", ".svg" };
+
+ private static readonly (string DataFormat, ClipboardFormat ClipboardFormat)[] DataFormats =
+ [
+ (StandardDataFormats.Text, ClipboardFormat.Text),
+ (StandardDataFormats.Html, ClipboardFormat.Html),
+ (StandardDataFormats.Bitmap, ClipboardFormat.Image),
+ ];
+
+ internal static async Task GetAvailableClipboardFormatsAsync(DataPackageView clipboardData)
+ {
+ var availableClipboardFormats = DataFormats.Aggregate(
+ ClipboardFormat.None,
+ (result, formatPair) => clipboardData.Contains(formatPair.DataFormat) ? (result | formatPair.ClipboardFormat) : result);
+
+ if (clipboardData.Contains(StandardDataFormats.StorageItems))
+ {
+ var storageItems = await clipboardData.GetStorageItemsAsync();
+
+ if (storageItems.Count == 1 && storageItems.Single() is StorageFile file && ImageFileTypes.Contains(file.FileType))
+ {
+ availableClipboardFormats |= ClipboardFormat.ImageFile;
+ }
+ }
+
+ return availableClipboardFormats;
+ }
+
internal static void SetClipboardTextContent(string text)
{
Logger.LogTrace();
@@ -26,31 +58,45 @@ namespace AdvancedPaste.Helpers
output.SetText(text);
Clipboard.SetContentWithOptions(output, null);
- // TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
- // Calling inside a loop makes it work.
- bool flushed = false;
- for (int i = 0; i < 5; i++)
+ Flush();
+ }
+ }
+
+ private static bool Flush()
+ {
+ // TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
+ // Calling inside a loop makes it work.
+ const int maxAttempts = 5;
+ for (int i = 1; i <= maxAttempts; i++)
+ {
+ try
{
- if (flushed)
+ Task.Run(Clipboard.Flush).Wait();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ if (i == maxAttempts)
{
- break;
- }
-
- try
- {
- Task.Run(() =>
- {
- Clipboard.Flush();
- }).Wait();
-
- flushed = true;
- }
- catch (Exception ex)
- {
- Logger.LogError("Clipboard.Flush() failed", ex);
+ Logger.LogError($"{nameof(Clipboard)}.{nameof(Flush)}() failed", ex);
}
}
}
+
+ return false;
+ }
+
+ private static async Task FlushAsync() => await Task.Run(Flush);
+
+ internal static async Task SetClipboardFileContentAsync(string fileName)
+ {
+ var storageFile = await StorageFile.GetFileFromPathAsync(fileName);
+
+ DataPackage output = new();
+ output.SetStorageItems([storageFile]);
+ Clipboard.SetContent(output);
+
+ await FlushAsync();
}
internal static void SetClipboardImageContent(RandomAccessStreamReference image)
@@ -63,30 +109,7 @@ namespace AdvancedPaste.Helpers
output.SetBitmap(image);
Clipboard.SetContentWithOptions(output, null);
- // TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
- // Calling inside a loop makes it work.
- bool flushed = false;
- for (int i = 0; i < 5; i++)
- {
- if (flushed)
- {
- break;
- }
-
- try
- {
- Task.Run(() =>
- {
- Clipboard.Flush();
- }).Wait();
-
- flushed = true;
- }
- catch (Exception ex)
- {
- Logger.LogError("Clipboard.Flush() failed", ex);
- }
- }
+ Flush();
}
}
@@ -136,5 +159,58 @@ namespace AdvancedPaste.Helpers
Logger.LogInfo("Paste sent");
}
+
+ internal static async Task GetClipboardTextOrHtmlTextAsync(DataPackageView clipboardData)
+ {
+ if (clipboardData.Contains(StandardDataFormats.Text))
+ {
+ return await clipboardData.GetTextAsync();
+ }
+ else if (clipboardData.Contains(StandardDataFormats.Html))
+ {
+ var html = await clipboardData.GetHtmlFormatAsync();
+ return HtmlUtilities.ConvertToText(html);
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+
+ internal static async Task GetClipboardHtmlContentAsync(DataPackageView clipboardData) =>
+ clipboardData.Contains(StandardDataFormats.Html) ? await clipboardData.GetHtmlFormatAsync() : string.Empty;
+
+ internal static async Task GetClipboardImageContentAsync(DataPackageView clipboardData)
+ {
+ using var stream = await GetClipboardImageStreamAsync(clipboardData);
+ if (stream != null)
+ {
+ var decoder = await BitmapDecoder.CreateAsync(stream);
+ return await decoder.GetSoftwareBitmapAsync();
+ }
+
+ return null;
+ }
+
+ private static async Task GetClipboardImageStreamAsync(DataPackageView clipboardData)
+ {
+ if (clipboardData.Contains(StandardDataFormats.StorageItems))
+ {
+ var storageItems = await clipboardData.GetStorageItemsAsync();
+ var file = storageItems.Count == 1 ? storageItems[0] as StorageFile : null;
+ if (file != null)
+ {
+ return await file.OpenReadAsync();
+ }
+ }
+
+ if (clipboardData.Contains(StandardDataFormats.Bitmap))
+ {
+ var bitmap = await clipboardData.GetBitmapAsync();
+ return await bitmap.OpenReadAsync();
+ }
+
+ return null;
+ }
}
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/IUserSettings.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/IUserSettings.cs
index fd72f67262..49dbfda945 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/IUserSettings.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/IUserSettings.cs
@@ -2,8 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.ObjectModel;
+using System;
+using System.Collections.Generic;
+using AdvancedPaste.Models;
using Microsoft.PowerToys.Settings.UI.Library;
namespace AdvancedPaste.Settings
@@ -16,6 +18,10 @@ namespace AdvancedPaste.Settings
public bool CloseAfterLosingFocus { get; }
- public ObservableCollection CustomActions { get; }
+ public IReadOnlyList CustomActions { get; }
+
+ public IReadOnlyList AdditionalActions { get; }
+
+ public event EventHandler Changed;
}
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs
new file mode 100644
index 0000000000..25b46fd160
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Globalization;
+using Windows.Graphics.Imaging;
+using Windows.Media.Ocr;
+using Windows.System.UserProfile;
+
+namespace AdvancedPaste.Helpers;
+
+public static class OcrHelpers
+{
+ public static async Task ExtractTextAsync(SoftwareBitmap bitmap)
+ {
+ var ocrLanguage = GetOCRLanguage() ?? throw new InvalidOperationException("Unable to determine OCR language");
+
+ var ocrEngine = OcrEngine.TryCreateFromLanguage(ocrLanguage) ?? throw new InvalidOperationException("Unable to create OCR engine");
+ var ocrResult = await ocrEngine.RecognizeAsync(bitmap);
+
+ return ocrResult.Text;
+ }
+
+ private static Language GetOCRLanguage()
+ {
+ var userLanguageTags = GlobalizationPreferences.Languages.ToList();
+
+ var languages = from language in OcrEngine.AvailableRecognizerLanguages
+ let tag = language.LanguageTag
+ where userLanguageTags.Contains(tag)
+ orderby userLanguageTags.IndexOf(tag)
+ select language;
+
+ return languages.FirstOrDefault();
+ }
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/UserSettings.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/UserSettings.cs
index 0bfb50c898..fe60dd7f53 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/UserSettings.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/UserSettings.cs
@@ -3,11 +3,13 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Collections.ObjectModel;
+using System.Collections.Generic;
using System.IO.Abstractions;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using AdvancedPaste.Models;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -20,6 +22,8 @@ namespace AdvancedPaste.Settings
private readonly TaskScheduler _taskScheduler;
private readonly IFileSystemWatcher _watcher;
private readonly object _loadingSettingsLock = new();
+ private readonly List _additionalActions;
+ private readonly List _customActions;
private const string AdvancedPasteModuleName = "AdvancedPaste";
private const int MaxNumberOfRetry = 5;
@@ -27,13 +31,17 @@ namespace AdvancedPaste.Settings
private bool _disposedValue;
private CancellationTokenSource _cancellationTokenSource;
+ public event EventHandler Changed;
+
public bool ShowCustomPreview { get; private set; }
public bool SendPasteKeyCombination { get; private set; }
public bool CloseAfterLosingFocus { get; private set; }
- public ObservableCollection CustomActions { get; private set; }
+ public IReadOnlyList AdditionalActions => _additionalActions;
+
+ public IReadOnlyList CustomActions => _customActions;
public UserSettings()
{
@@ -42,8 +50,8 @@ namespace AdvancedPaste.Settings
ShowCustomPreview = true;
SendPasteKeyCombination = true;
CloseAfterLosingFocus = false;
- CustomActions = [];
-
+ _additionalActions = [];
+ _customActions = [];
_taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
LoadSettingsFromJson();
@@ -88,18 +96,29 @@ namespace AdvancedPaste.Settings
{
void UpdateSettings()
{
- ShowCustomPreview = settings.Properties.ShowCustomPreview;
- SendPasteKeyCombination = settings.Properties.SendPasteKeyCombination;
- CloseAfterLosingFocus = settings.Properties.CloseAfterLosingFocus;
+ var properties = settings.Properties;
- CustomActions.Clear();
- foreach (var customAction in settings.Properties.CustomActions.Value)
- {
- if (customAction.IsShown && customAction.IsValid)
- {
- CustomActions.Add(customAction);
- }
- }
+ ShowCustomPreview = properties.ShowCustomPreview;
+ SendPasteKeyCombination = properties.SendPasteKeyCombination;
+ CloseAfterLosingFocus = properties.CloseAfterLosingFocus;
+
+ var sourceAdditionalActions = properties.AdditionalActions;
+ (PasteFormats Format, IAdvancedPasteAction[] Actions)[] additionalActionFormats =
+ [
+ (PasteFormats.ImageToText, [sourceAdditionalActions.ImageToText]),
+ (PasteFormats.PasteAsTxtFile, [sourceAdditionalActions.PasteAsFile, sourceAdditionalActions.PasteAsFile.PasteAsTxtFile]),
+ (PasteFormats.PasteAsPngFile, [sourceAdditionalActions.PasteAsFile, sourceAdditionalActions.PasteAsFile.PasteAsPngFile]),
+ (PasteFormats.PasteAsHtmlFile, [sourceAdditionalActions.PasteAsFile, sourceAdditionalActions.PasteAsFile.PasteAsHtmlFile])
+ ];
+
+ _additionalActions.Clear();
+ _additionalActions.AddRange(additionalActionFormats.Where(tuple => tuple.Actions.All(action => action.IsShown))
+ .Select(tuple => tuple.Format));
+
+ _customActions.Clear();
+ _customActions.AddRange(properties.CustomActions.Value.Where(customAction => customAction.IsShown && customAction.IsValid));
+
+ Changed?.Invoke(this, EventArgs.Empty);
}
Task.Factory
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardFormat.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardFormat.cs
new file mode 100644
index 0000000000..a63e79735e
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardFormat.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace AdvancedPaste.Models;
+
+[Flags]
+public enum ClipboardFormat
+{
+ None,
+ Text = 1 << 0,
+ Html = 1 << 1,
+ Audio = 1 << 2,
+ Image = 1 << 3,
+ ImageFile = 1 << 4,
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardItem.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardItem.cs
index 1ff749753e..3927949064 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardItem.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/ClipboardItem.cs
@@ -5,14 +5,13 @@
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.ApplicationModel.DataTransfer;
-namespace AdvancedPaste.Models
+namespace AdvancedPaste.Models;
+
+public class ClipboardItem
{
- public class ClipboardItem
- {
- public string Content { get; set; }
+ public string Content { get; set; }
- public ClipboardHistoryItem Item { get; set; }
+ public ClipboardHistoryItem Item { get; set; }
- public BitmapImage Image { get; set; }
- }
+ public BitmapImage Image { get; set; }
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/CustomActionActivatedEventArgs.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/CustomActionActivatedEventArgs.cs
index d321cb01f6..d4846e01be 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Models/CustomActionActivatedEventArgs.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/CustomActionActivatedEventArgs.cs
@@ -6,9 +6,9 @@ using System;
namespace AdvancedPaste.Models;
-public sealed class CustomActionActivatedEventArgs(string text, bool forcePasteCustom) : EventArgs
+public sealed class CustomActionActivatedEventArgs(string text, bool pasteResult) : EventArgs
{
- public string Text { get; private set; } = text;
+ public string Text { get; private init; } = text;
- public bool ForcePasteCustom { get; private set; } = forcePasteCustom;
+ public bool PasteResult { get; private init; } = pasteResult;
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionException.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionException.cs
new file mode 100644
index 0000000000..fed4e24c50
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionException.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace AdvancedPaste.Models;
+
+public sealed class PasteActionException(string message) : Exception(message)
+{
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionSource.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionSource.cs
new file mode 100644
index 0000000000..bdfabfbcc3
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteActionSource.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace AdvancedPaste.Models;
+
+public enum PasteActionSource
+{
+ ContextMenu,
+ InAppKeyboardShortcut,
+ GlobalKeyboardShortcut,
+ PromptBox,
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormat.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormat.cs
index 6f5103be3e..c38a54b843 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormat.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormat.cs
@@ -2,38 +2,62 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
using Microsoft.PowerToys.Settings.UI.Library;
namespace AdvancedPaste.Models;
-public partial class PasteFormat : ObservableObject
+[DebuggerDisplay("{Name} IsEnabled={IsEnabled} ShortcutText={ShortcutText}")]
+public sealed class PasteFormat
{
- [ObservableProperty]
- private string _shortcutText = string.Empty;
+ public static readonly IReadOnlyDictionary MetadataDict =
+ typeof(PasteFormats).GetFields()
+ .Where(field => field.IsLiteral)
+ .ToDictionary(field => (PasteFormats)field.GetRawConstantValue(), field => field.GetCustomAttribute());
- [ObservableProperty]
- private string _toolTip = string.Empty;
-
- public PasteFormat()
+ private PasteFormat(PasteFormats format, ClipboardFormat clipboardFormats, bool isAIServiceEnabled)
{
+ Format = format;
+ IsEnabled = SupportsClipboardFormats(clipboardFormats) && (isAIServiceEnabled || !Metadata.RequiresAIService);
}
- public PasteFormat(AdvancedPasteCustomAction customAction, string shortcutText)
+ public PasteFormat(PasteFormats format, ClipboardFormat clipboardFormats, bool isAIServiceEnabled, Func resourceLoader)
+ : this(format, clipboardFormats, isAIServiceEnabled)
+ {
+ Name = Metadata.ResourceId == null ? string.Empty : resourceLoader(Metadata.ResourceId);
+ Prompt = string.Empty;
+ }
+
+ public PasteFormat(AdvancedPasteCustomAction customAction, ClipboardFormat clipboardFormats, bool isAIServiceEnabled)
+ : this(PasteFormats.Custom, clipboardFormats, isAIServiceEnabled)
{
- IconGlyph = "\uE945";
Name = customAction.Name;
Prompt = customAction.Prompt;
- Format = PasteFormats.Custom;
- ShortcutText = shortcutText;
- ToolTip = customAction.Prompt;
}
- public string IconGlyph { get; init; }
+ public PasteFormatMetadataAttribute Metadata => MetadataDict[Format];
- public string Name { get; init; }
+ public string IconGlyph => Metadata.IconGlyph;
- public PasteFormats Format { get; init; }
+ public string Name { get; private init; }
- public string Prompt { get; init; } = string.Empty;
+ public PasteFormats Format { get; private init; }
+
+ public string Prompt { get; private init; }
+
+ public bool IsEnabled { get; private init; }
+
+ public double Opacity => IsEnabled ? 1 : 0.5;
+
+ public string ToolTip => string.IsNullOrEmpty(Prompt) ? $"{Name} ({ShortcutText})" : Prompt;
+
+ public string Query => string.IsNullOrEmpty(Prompt) ? Name : Prompt;
+
+ public string ShortcutText { get; set; } = string.Empty;
+
+ public bool SupportsClipboardFormats(ClipboardFormat clipboardFormats) => (clipboardFormats & Metadata.SupportedClipboardFormats) != ClipboardFormat.None;
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormatMetadataAttribute.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormatMetadataAttribute.cs
new file mode 100644
index 0000000000..cb3a8a954e
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormatMetadataAttribute.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace AdvancedPaste.Models;
+
+[AttributeUsage(AttributeTargets.Field)]
+public sealed class PasteFormatMetadataAttribute : Attribute
+{
+ public bool IsCoreAction { get; init; }
+
+ public string ResourceId { get; init; }
+
+ public string IconGlyph { get; init; }
+
+ public bool RequiresAIService { get; init; }
+
+ public ClipboardFormat SupportedClipboardFormats { get; init; }
+
+ public string IPCKey { get; init; }
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormats.cs b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormats.cs
index ba48fe6586..fe710d5410 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormats.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Models/PasteFormats.cs
@@ -2,13 +2,33 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace AdvancedPaste.Models
+using Microsoft.PowerToys.Settings.UI.Library;
+
+namespace AdvancedPaste.Models;
+
+public enum PasteFormats
{
- public enum PasteFormats
- {
- PlainText,
- Markdown,
- Json,
- Custom,
- }
+ [PasteFormatMetadata(IsCoreAction = true, ResourceId = "PasteAsPlainText", IconGlyph = "\uE8E9", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Text)]
+ PlainText,
+
+ [PasteFormatMetadata(IsCoreAction = true, ResourceId = "PasteAsMarkdown", IconGlyph = "\ue8a5", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Text)]
+ Markdown,
+
+ [PasteFormatMetadata(IsCoreAction = true, ResourceId = "PasteAsJson", IconGlyph = "\uE943", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Text)]
+ Json,
+
+ [PasteFormatMetadata(IsCoreAction = false, ResourceId = "ImageToText", IconGlyph = "\uE91B", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Image | ClipboardFormat.ImageFile, IPCKey = AdvancedPasteAdditionalActions.PropertyNames.ImageToText)]
+ ImageToText,
+
+ [PasteFormatMetadata(IsCoreAction = false, ResourceId = "PasteAsTxtFile", IconGlyph = "\uE8D2", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Text | ClipboardFormat.Html, IPCKey = AdvancedPastePasteAsFileAction.PropertyNames.PasteAsTxtFile)]
+ PasteAsTxtFile,
+
+ [PasteFormatMetadata(IsCoreAction = false, ResourceId = "PasteAsPngFile", IconGlyph = "\uE8B9", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Image | ClipboardFormat.ImageFile, IPCKey = AdvancedPastePasteAsFileAction.PropertyNames.PasteAsPngFile)]
+ PasteAsPngFile,
+
+ [PasteFormatMetadata(IsCoreAction = false, ResourceId = "PasteAsHtmlFile", IconGlyph = "\uF6FA", RequiresAIService = false, SupportedClipboardFormats = ClipboardFormat.Html, IPCKey = AdvancedPastePasteAsFileAction.PropertyNames.PasteAsHtmlFile)]
+ PasteAsHtmlFile,
+
+ [PasteFormatMetadata(IsCoreAction = false, IconGlyph = "\uE945", RequiresAIService = true, SupportedClipboardFormats = ClipboardFormat.Text)]
+ Custom,
}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Services/IPasteFormatExecutor.cs b/src/modules/AdvancedPaste/AdvancedPaste/Services/IPasteFormatExecutor.cs
new file mode 100644
index 0000000000..e0bb39ab7c
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Services/IPasteFormatExecutor.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading.Tasks;
+using AdvancedPaste.Models;
+
+namespace AdvancedPaste.Services;
+
+public interface IPasteFormatExecutor
+{
+ Task ExecutePasteFormatAsync(PasteFormat pasteFormat, PasteActionSource source);
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Services/PasteFormatExecutor.cs b/src/modules/AdvancedPaste/AdvancedPaste/Services/PasteFormatExecutor.cs
new file mode 100644
index 0000000000..f77cf8ef99
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Services/PasteFormatExecutor.cs
@@ -0,0 +1,253 @@
+// 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;
+using System.Threading.Tasks;
+using AdvancedPaste.Helpers;
+using AdvancedPaste.Models;
+using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
+using Windows.ApplicationModel.DataTransfer;
+using Windows.Graphics.Imaging;
+using Windows.Storage.Streams;
+
+namespace AdvancedPaste.Services;
+
+public sealed class PasteFormatExecutor(AICompletionsHelper aiHelper) : IPasteFormatExecutor
+{
+ private readonly AICompletionsHelper _aiHelper = aiHelper;
+
+ public async Task ExecutePasteFormatAsync(PasteFormat pasteFormat, PasteActionSource source)
+ {
+ if (!pasteFormat.IsEnabled)
+ {
+ return null;
+ }
+
+ WriteTelemetry(pasteFormat.Format, source);
+
+ return await ExecutePasteFormatCoreAsync(pasteFormat, Clipboard.GetContent());
+ }
+
+ private async Task ExecutePasteFormatCoreAsync(PasteFormat pasteFormat, DataPackageView clipboardData)
+ {
+ switch (pasteFormat.Format)
+ {
+ case PasteFormats.PlainText:
+ ToPlainText(clipboardData);
+ return null;
+
+ case PasteFormats.Markdown:
+ ToMarkdown(clipboardData);
+ return null;
+
+ case PasteFormats.Json:
+ ToJson(clipboardData);
+ return null;
+
+ case PasteFormats.ImageToText:
+ await ImageToTextAsync(clipboardData);
+ return null;
+
+ case PasteFormats.PasteAsTxtFile:
+ await ToTxtFileAsync(clipboardData);
+ return null;
+
+ case PasteFormats.PasteAsPngFile:
+ await ToPngFileAsync(clipboardData);
+ return null;
+
+ case PasteFormats.PasteAsHtmlFile:
+ await ToHtmlFileAsync(clipboardData);
+ return null;
+
+ case PasteFormats.Custom:
+ return await ToCustomAsync(pasteFormat.Prompt, clipboardData);
+
+ default:
+ throw new ArgumentException($"Unknown paste format {pasteFormat.Format}", nameof(pasteFormat));
+ }
+ }
+
+ private static void WriteTelemetry(PasteFormats format, PasteActionSource source)
+ {
+ switch (source)
+ {
+ case PasteActionSource.ContextMenu:
+ PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteFormatClickedEvent(format));
+ break;
+
+ case PasteActionSource.InAppKeyboardShortcut:
+ PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteInAppKeyboardShortcutEvent(format));
+ break;
+
+ case PasteActionSource.GlobalKeyboardShortcut:
+ case PasteActionSource.PromptBox:
+ break; // no telemetry yet for these sources
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(format));
+ }
+ }
+
+ private void ToPlainText(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+ SetClipboardTextContent(MarkdownHelper.PasteAsPlainTextFromClipboard(clipboardData));
+ }
+
+ private void ToMarkdown(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+ SetClipboardTextContent(MarkdownHelper.ToMarkdown(clipboardData));
+ }
+
+ private void ToJson(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+ SetClipboardTextContent(JsonHelper.ToJsonFromXmlOrCsv(clipboardData));
+ }
+
+ private async Task ImageToTextAsync(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+
+ var bitmap = await ClipboardHelper.GetClipboardImageContentAsync(clipboardData);
+ var text = await OcrHelpers.ExtractTextAsync(bitmap);
+ SetClipboardTextContent(text);
+ }
+
+ private async Task ToPngFileAsync(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+
+ var clipboardBitmap = await ClipboardHelper.GetClipboardImageContentAsync(clipboardData);
+
+ using var pngStream = new InMemoryRandomAccessStream();
+ var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, pngStream);
+ encoder.SetSoftwareBitmap(clipboardBitmap);
+ await encoder.FlushAsync();
+
+ await SetClipboardFileContentAsync(pngStream.AsStreamForRead(), "png");
+ }
+
+ private async Task ToTxtFileAsync(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+
+ var text = await ClipboardHelper.GetClipboardTextOrHtmlTextAsync(clipboardData);
+ await SetClipboardFileContentAsync(text, "txt");
+ }
+
+ private async Task ToHtmlFileAsync(DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+
+ var cfHtml = await ClipboardHelper.GetClipboardHtmlContentAsync(clipboardData);
+ var html = RemoveHtmlMetadata(cfHtml);
+
+ await SetClipboardFileContentAsync(html, "html");
+ }
+
+ ///
+ /// Removes leading CF_HTML metadata from HTML clipboard data.
+ /// See: https://learn.microsoft.com/en-us/windows/win32/dataxchg/html-clipboard-format
+ ///
+ private static string RemoveHtmlMetadata(string cfHtml)
+ {
+ int? GetIntTagValue(string tagName)
+ {
+ var tagNameWithColon = tagName + ":";
+ int tagStartPos = cfHtml.IndexOf(tagNameWithColon, StringComparison.InvariantCulture);
+
+ const int tagValueLength = 10;
+ return tagStartPos != -1 && int.TryParse(cfHtml.AsSpan(tagStartPos + tagNameWithColon.Length, tagValueLength), CultureInfo.InvariantCulture, out int result) ? result : null;
+ }
+
+ var startFragmentIndex = GetIntTagValue("StartFragment");
+ var endFragmentIndex = GetIntTagValue("EndFragment");
+
+ return (startFragmentIndex == null || endFragmentIndex == null) ? cfHtml : cfHtml[startFragmentIndex.Value..endFragmentIndex.Value];
+ }
+
+ private static async Task SetClipboardFileContentAsync(string data, string fileExtension)
+ {
+ if (string.IsNullOrEmpty(data))
+ {
+ throw new ArgumentException($"Empty value in {nameof(SetClipboardFileContentAsync)}", nameof(data));
+ }
+
+ var path = GetPasteAsFileTempFilePath(fileExtension);
+
+ await File.WriteAllTextAsync(path, data);
+ await ClipboardHelper.SetClipboardFileContentAsync(path);
+ }
+
+ private static async Task SetClipboardFileContentAsync(Stream stream, string fileExtension)
+ {
+ var path = GetPasteAsFileTempFilePath(fileExtension);
+
+ using var fileStream = File.Create(path);
+ await stream.CopyToAsync(fileStream);
+
+ await ClipboardHelper.SetClipboardFileContentAsync(path);
+ }
+
+ private static string GetPasteAsFileTempFilePath(string fileExtension)
+ {
+ var prefix = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsFile_FilePrefix");
+ var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture);
+
+ return Path.Combine(Path.GetTempPath(), $"{prefix}{timestamp}.{fileExtension}");
+ }
+
+ private async Task ToCustomAsync(string prompt, DataPackageView clipboardData)
+ {
+ Logger.LogTrace();
+
+ if (string.IsNullOrWhiteSpace(prompt))
+ {
+ return string.Empty;
+ }
+
+ if (!clipboardData.Contains(StandardDataFormats.Text))
+ {
+ Logger.LogWarning("Clipboard does not contain text data");
+ return string.Empty;
+ }
+
+ var currentClipboardText = await clipboardData.GetTextAsync();
+
+ if (string.IsNullOrWhiteSpace(currentClipboardText))
+ {
+ Logger.LogWarning("Clipboard has no usable text data");
+ return string.Empty;
+ }
+
+ var aiResponse = await Task.Run(() => _aiHelper.AIFormatString(prompt, currentClipboardText));
+
+ return aiResponse.ApiRequestStatus == (int)HttpStatusCode.OK
+ ? aiResponse.Response
+ : throw new PasteActionException(TranslateErrorText(aiResponse.ApiRequestStatus));
+ }
+
+ private void SetClipboardTextContent(string content)
+ {
+ if (!string.IsNullOrEmpty(content))
+ {
+ ClipboardHelper.SetClipboardTextContent(content);
+ }
+ }
+
+ private static string TranslateErrorText(int apiRequestStatus) => (HttpStatusCode)apiRequestStatus switch
+ {
+ HttpStatusCode.TooManyRequests => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyTooManyRequests"),
+ HttpStatusCode.Unauthorized => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyUnauthorized"),
+ HttpStatusCode.OK => string.Empty,
+ _ => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyError") + apiRequestStatus.ToString(CultureInfo.InvariantCulture),
+ };
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw b/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw
index dd2720732c..0ec81547e2 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw
+++ b/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw
@@ -120,9 +120,12 @@
AI can make mistakes.
-
- Clipboard data is not text
+
+ Clipboard does not contain any usable formats
+
+ Clipboard data is not text
+
To custom with AI is not enabled
@@ -135,6 +138,9 @@
OpenAI request failed with status code:
+
+ An error occurred during the paste operation
+
Clipboard history
@@ -151,7 +157,7 @@
Privacy
- Connecting to AI services and generating output..
+ Generating output...
Paste as JSON
@@ -162,6 +168,18 @@
Paste as plain text
+
+ Image to text
+
+
+ Paste as .txt file
+
+
+ Paste as .png file
+
+
+ Paste as .html file
+
Paste
@@ -228,4 +246,7 @@
Ctrl
+
+ PowerToys_Paste_
+
\ No newline at end of file
diff --git a/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs b/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs
index 4d59e327af..f2e461e47f 100644
--- a/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs
+++ b/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs
@@ -3,21 +3,20 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Globalization;
using System.Linq;
-using System.Net;
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
using AdvancedPaste.Models;
+using AdvancedPaste.Services;
using AdvancedPaste.Settings;
using Common.UI;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
-using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
using Microsoft.Win32;
using Windows.ApplicationModel.DataTransfer;
@@ -28,67 +27,66 @@ using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
namespace AdvancedPaste.ViewModels
{
- public partial class OptionsViewModel : ObservableObject, IDisposable
+ public sealed partial class OptionsViewModel : ObservableObject, IDisposable
{
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
private readonly DispatcherTimer _clipboardTimer;
private readonly IUserSettings _userSettings;
- private readonly AICompletionsHelper aiHelper;
- private readonly App app = App.Current as App;
- private readonly PasteFormat[] _allStandardPasteFormats;
+ private readonly IPasteFormatExecutor _pasteFormatExecutor;
+ private readonly AICompletionsHelper _aiHelper;
public DataPackageView ClipboardData { get; set; }
[ObservableProperty]
- [NotifyPropertyChangedFor(nameof(InputTxtBoxPlaceholderText))]
- [NotifyPropertyChangedFor(nameof(GeneralErrorText))]
[NotifyPropertyChangedFor(nameof(IsCustomAIEnabled))]
- private bool _isClipboardDataText;
+ [NotifyPropertyChangedFor(nameof(ClipboardHasData))]
+ [NotifyPropertyChangedFor(nameof(InputTxtBoxPlaceholderText))]
+ [NotifyPropertyChangedFor(nameof(AIDisabledErrorText))]
+ private ClipboardFormat _availableClipboardFormats;
[ObservableProperty]
private bool _clipboardHistoryEnabled;
[ObservableProperty]
- [NotifyPropertyChangedFor(nameof(InputTxtBoxPlaceholderText))]
- [NotifyPropertyChangedFor(nameof(GeneralErrorText))]
- [NotifyPropertyChangedFor(nameof(IsPasteWithAIEnabled))]
+ [NotifyPropertyChangedFor(nameof(AIDisabledErrorText))]
+ [NotifyPropertyChangedFor(nameof(IsAIServiceEnabled))]
[NotifyPropertyChangedFor(nameof(IsCustomAIEnabled))]
private bool _isAllowedByGPO;
[ObservableProperty]
- [NotifyPropertyChangedFor(nameof(ApiErrorText))]
- private int _apiRequestStatus;
+ private string _pasteOperationErrorText;
[ObservableProperty]
private string _query = string.Empty;
private bool _pasteFormatsDirty;
+ [ObservableProperty]
+ private bool _busy;
+
public ObservableCollection StandardPasteFormats { get; } = [];
public ObservableCollection CustomActionPasteFormats { get; } = [];
- public bool IsPasteWithAIEnabled => IsAllowedByGPO && aiHelper.IsAIEnabled;
+ public bool IsAIServiceEnabled => IsAllowedByGPO && _aiHelper.IsAIEnabled;
- public bool IsCustomAIEnabled => IsPasteWithAIEnabled && IsClipboardDataText;
+ public bool IsCustomAIEnabled => IsAIServiceEnabled && ClipboardHasText;
+
+ public bool ClipboardHasData => AvailableClipboardFormats != ClipboardFormat.None;
+
+ private bool ClipboardHasText => AvailableClipboardFormats.HasFlag(ClipboardFormat.Text);
+
+ private bool Visible => GetMainWindow()?.Visible is true;
public event EventHandler CustomActionActivated;
- public OptionsViewModel(IUserSettings userSettings)
+ public OptionsViewModel(AICompletionsHelper aiHelper, IUserSettings userSettings, IPasteFormatExecutor pasteFormatExecutor)
{
- aiHelper = new AICompletionsHelper();
+ _aiHelper = aiHelper;
_userSettings = userSettings;
+ _pasteFormatExecutor = pasteFormatExecutor;
- ApiRequestStatus = (int)HttpStatusCode.OK;
-
- _allStandardPasteFormats =
- [
- new PasteFormat { IconGlyph = "\uE8E9", Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsPlainText"), Format = PasteFormats.PlainText },
- new PasteFormat { IconGlyph = "\ue8a5", Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsMarkdown"), Format = PasteFormats.Markdown },
- new PasteFormat { IconGlyph = "\uE943", Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsJson"), Format = PasteFormats.Json },
- ];
-
- GeneratedResponses = new ObservableCollection();
+ GeneratedResponses = [];
GeneratedResponses.CollectionChanged += (s, e) =>
{
OnPropertyChanged(nameof(HasMultipleResponses));
@@ -96,28 +94,31 @@ namespace AdvancedPaste.ViewModels
};
ClipboardHistoryEnabled = IsClipboardHistoryEnabled();
- ReadClipboard();
UpdateOpenAIKey();
_clipboardTimer = new() { Interval = TimeSpan.FromSeconds(1) };
_clipboardTimer.Tick += ClipboardTimer_Tick;
_clipboardTimer.Start();
RefreshPasteFormats();
- _userSettings.CustomActions.CollectionChanged += (_, _) => EnqueueRefreshPasteFormats();
+ _userSettings.Changed += (_, _) => EnqueueRefreshPasteFormats();
PropertyChanged += (_, e) =>
{
- if (e.PropertyName == nameof(Query) || e.PropertyName == nameof(IsPasteWithAIEnabled))
+ string[] dirtyingProperties = [nameof(Query), nameof(IsAIServiceEnabled), nameof(IsCustomAIEnabled), nameof(AvailableClipboardFormats)];
+
+ if (dirtyingProperties.Contains(e.PropertyName))
{
EnqueueRefreshPasteFormats();
}
};
}
- private void ClipboardTimer_Tick(object sender, object e)
+ private static MainWindow GetMainWindow() => (App.Current as App)?.GetMainWindow();
+
+ private async void ClipboardTimer_Tick(object sender, object e)
{
- if (app.GetMainWindow()?.Visible is true)
+ if (Visible)
{
- ReadClipboard();
+ await ReadClipboardAsync();
UpdateAllowedByGPO();
}
}
@@ -137,10 +138,12 @@ namespace AdvancedPaste.ViewModels
});
}
+ private PasteFormat CreatePasteFormat(PasteFormats format) => new(format, AvailableClipboardFormats, IsAIServiceEnabled, ResourceLoaderInstance.ResourceLoader.GetString);
+
+ private PasteFormat CreatePasteFormat(AdvancedPasteCustomAction customAction) => new(customAction, AvailableClipboardFormats, IsAIServiceEnabled);
+
private void RefreshPasteFormats()
{
- bool Filter(string text) => text.Contains(Query, StringComparison.CurrentCultureIgnoreCase);
-
var ctrlString = ResourceLoaderInstance.ResourceLoader.GetString("CtrlKey");
int shortcutNum = 0;
@@ -150,28 +153,33 @@ namespace AdvancedPaste.ViewModels
return shortcutNum <= 9 ? $"{ctrlString}+{shortcutNum}" : string.Empty;
}
- StandardPasteFormats.Clear();
- foreach (var format in _allStandardPasteFormats)
+ IEnumerable FilterAndSort(IEnumerable pasteFormats) =>
+ from pasteFormat in pasteFormats
+ let comparison = StringComparison.CurrentCultureIgnoreCase
+ where pasteFormat.Name.Contains(Query, comparison) || pasteFormat.Prompt.Contains(Query, comparison)
+ orderby pasteFormat.IsEnabled descending
+ select pasteFormat;
+
+ void UpdateFormats(ObservableCollection collection, IEnumerable pasteFormats)
{
- if (Filter(format.Name))
+ collection.Clear();
+
+ foreach (var format in FilterAndSort(pasteFormats))
{
- format.ShortcutText = GetNextShortcutText();
- format.ToolTip = $"{format.Name} ({format.ShortcutText})";
- StandardPasteFormats.Add(format);
+ if (format.IsEnabled)
+ {
+ format.ShortcutText = GetNextShortcutText();
+ }
+
+ collection.Add(format);
}
}
- CustomActionPasteFormats.Clear();
- if (IsPasteWithAIEnabled)
- {
- foreach (var customAction in _userSettings.CustomActions)
- {
- if (Filter(customAction.Name) || Filter(customAction.Prompt))
- {
- CustomActionPasteFormats.Add(new PasteFormat(customAction, GetNextShortcutText()));
- }
- }
- }
+ UpdateFormats(StandardPasteFormats, Enum.GetValues()
+ .Where(format => PasteFormat.MetadataDict[format].IsCoreAction || _userSettings.AdditionalActions.Contains(format))
+ .Select(CreatePasteFormat));
+
+ UpdateFormats(CustomActionPasteFormats, IsAIServiceEnabled ? _userSettings.CustomActions.Select(CreatePasteFormat) : []);
}
public void Dispose()
@@ -180,26 +188,34 @@ namespace AdvancedPaste.ViewModels
GC.SuppressFinalize(this);
}
- public void ReadClipboard()
+ public async Task ReadClipboardAsync()
{
+ if (Busy)
+ {
+ return;
+ }
+
ClipboardData = Clipboard.GetContent();
- IsClipboardDataText = ClipboardData.Contains(StandardDataFormats.Text);
+ AvailableClipboardFormats = await ClipboardHelper.GetAvailableClipboardFormatsAsync(ClipboardData);
}
- public void OnShow()
+ public async Task OnShowAsync()
{
- ReadClipboard();
+ PasteOperationErrorText = string.Empty;
+ Query = string.Empty;
+
+ await ReadClipboardAsync();
if (UpdateOpenAIKey())
{
- app.GetMainWindow()?.StartLoading();
+ GetMainWindow()?.StartLoading();
_dispatcherQueue.TryEnqueue(() =>
{
- app.GetMainWindow()?.FinishLoading(aiHelper.IsAIEnabled);
+ GetMainWindow()?.FinishLoading(_aiHelper.IsAIEnabled);
OnPropertyChanged(nameof(InputTxtBoxPlaceholderText));
- OnPropertyChanged(nameof(GeneralErrorText));
- OnPropertyChanged(nameof(IsPasteWithAIEnabled));
+ OnPropertyChanged(nameof(AIDisabledErrorText));
+ OnPropertyChanged(nameof(IsAIServiceEnabled));
OnPropertyChanged(nameof(IsCustomAIEnabled));
});
}
@@ -209,7 +225,7 @@ namespace AdvancedPaste.ViewModels
}
// List to store generated responses
- public ObservableCollection GeneratedResponses { get; set; } = new ObservableCollection();
+ public ObservableCollection GeneratedResponses { get; set; } = [];
// Index to keep track of the current response
private int _currentResponseIndex;
@@ -228,30 +244,20 @@ namespace AdvancedPaste.ViewModels
}
}
- public bool HasMultipleResponses
- {
- get => GeneratedResponses.Count > 1;
- }
+ public bool HasMultipleResponses => GeneratedResponses.Count > 1;
public string CurrentIndexDisplay => $"{CurrentResponseIndex + 1}/{GeneratedResponses.Count}";
public string InputTxtBoxPlaceholderText
+ => ResourceLoaderInstance.ResourceLoader.GetString(ClipboardHasData ? "CustomFormatTextBox/PlaceholderText" : "ClipboardEmptyWarning");
+
+ public string AIDisabledErrorText
{
get
{
- app.GetMainWindow().ClearInputText();
-
- return IsClipboardDataText ? ResourceLoaderInstance.ResourceLoader.GetString("CustomFormatTextBox/PlaceholderText") : GeneralErrorText;
- }
- }
-
- public string GeneralErrorText
- {
- get
- {
- if (!IsClipboardDataText)
+ if (!ClipboardHasText)
{
- return ResourceLoaderInstance.ResourceLoader.GetString("ClipboardDataTypeMismatchWarning");
+ return ResourceLoaderInstance.ResourceLoader.GetString("ClipboardDataNotTextWarning");
}
if (!IsAllowedByGPO)
@@ -259,7 +265,7 @@ namespace AdvancedPaste.ViewModels
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAIGpoDisabled");
}
- if (!aiHelper.IsAIEnabled)
+ if (!_aiHelper.IsAIEnabled)
{
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAINotConfigured");
}
@@ -270,17 +276,6 @@ namespace AdvancedPaste.ViewModels
}
}
- public string ApiErrorText
- {
- get => (HttpStatusCode)ApiRequestStatus switch
- {
- HttpStatusCode.TooManyRequests => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyTooManyRequests"),
- HttpStatusCode.Unauthorized => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyUnauthorized"),
- HttpStatusCode.OK => string.Empty,
- _ => ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyError") + ApiRequestStatus.ToString(CultureInfo.InvariantCulture),
- };
- }
-
[ObservableProperty]
private string _customFormatResult;
@@ -289,9 +284,17 @@ namespace AdvancedPaste.ViewModels
{
var text = GeneratedResponses.ElementAtOrDefault(CurrentResponseIndex);
- if (text != null)
+ if (!string.IsNullOrEmpty(text))
{
- PasteCustomFunction(text);
+ ClipboardHelper.SetClipboardTextContent(text);
+ HideWindow();
+
+ if (_userSettings.SendPasteKeyCombination)
+ {
+ ClipboardHelper.SendPasteKeyCombination();
+ }
+
+ Query = string.Empty;
}
}
@@ -320,190 +323,120 @@ namespace AdvancedPaste.ViewModels
public void OpenSettings()
{
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.AdvancedPaste, true);
- (App.Current as App).GetMainWindow().Close();
+ GetMainWindow()?.Close();
}
- private void SetClipboardContentAndHideWindow(string content)
+ internal async Task ExecutePasteFormatAsync(PasteFormats format, PasteActionSource source)
{
- if (!string.IsNullOrEmpty(content))
- {
- ClipboardHelper.SetClipboardTextContent(content);
- }
-
- if (app.GetMainWindow() != null)
- {
- Windows.Win32.Foundation.HWND hwnd = (Windows.Win32.Foundation.HWND)app.GetMainWindow().GetWindowHandle();
- Windows.Win32.PInvoke.ShowWindow(hwnd, Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
- }
+ await ReadClipboardAsync();
+ await ExecutePasteFormatAsync(CreatePasteFormat(format), source);
}
- internal void ToPlainTextFunction()
+ internal async Task ExecutePasteFormatAsync(PasteFormat pasteFormat, PasteActionSource source)
{
- try
- {
- Logger.LogTrace();
-
- string outputString = MarkdownHelper.PasteAsPlainTextFromClipboard(ClipboardData);
-
- SetClipboardContentAndHideWindow(outputString);
-
- if (_userSettings.SendPasteKeyCombination)
- {
- ClipboardHelper.SendPasteKeyCombination();
- }
- }
- catch
- {
- }
- }
-
- internal void ToMarkdownFunction(bool pasteAlways = false)
- {
- try
- {
- Logger.LogTrace();
-
- string outputString = MarkdownHelper.ToMarkdown(ClipboardData);
-
- SetClipboardContentAndHideWindow(outputString);
-
- if (pasteAlways || _userSettings.SendPasteKeyCombination)
- {
- ClipboardHelper.SendPasteKeyCombination();
- }
- }
- catch
- {
- }
- }
-
- internal void ToJsonFunction(bool pasteAlways = false)
- {
- try
- {
- Logger.LogTrace();
-
- string jsonText = JsonHelper.ToJsonFromXmlOrCsv(ClipboardData);
-
- SetClipboardContentAndHideWindow(jsonText);
-
- if (pasteAlways || _userSettings.SendPasteKeyCombination)
- {
- ClipboardHelper.SendPasteKeyCombination();
- }
- }
- catch
- {
- }
- }
-
- internal void ExecutePasteFormat(VirtualKey key)
- {
- var index = key - VirtualKey.Number1;
- var pasteFormat = StandardPasteFormats.ElementAtOrDefault(index) ?? CustomActionPasteFormats.ElementAtOrDefault(index - StandardPasteFormats.Count);
-
- if (pasteFormat != null)
- {
- ExecutePasteFormat(pasteFormat);
- PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteInAppKeyboardShortcutEvent(pasteFormat.Format));
- }
- }
-
- internal void ExecutePasteFormat(PasteFormat pasteFormat)
- {
- if (!IsClipboardDataText || (pasteFormat.Format == PasteFormats.Custom && !IsCustomAIEnabled))
+ if (Busy)
{
+ Logger.LogWarning($"Execution of {pasteFormat.Format} from {source} suppressed as busy");
return;
}
- switch (pasteFormat.Format)
+ if (!pasteFormat.IsEnabled)
{
- case PasteFormats.PlainText:
- ToPlainTextFunction();
- break;
+ var resourceId = pasteFormat.SupportsClipboardFormats(AvailableClipboardFormats) ? "PasteError" : "ClipboardEmptyWarning";
+ PasteOperationErrorText = ResourceLoaderInstance.ResourceLoader.GetString(resourceId);
+ return;
+ }
- case PasteFormats.Markdown:
- ToMarkdownFunction();
- break;
+ Busy = true;
+ PasteOperationErrorText = string.Empty;
+ Query = pasteFormat.Query;
- case PasteFormats.Json:
- ToJsonFunction();
- break;
+ if (pasteFormat.Format == PasteFormats.Custom)
+ {
+ SaveQuery(Query);
+ }
- case PasteFormats.Custom:
- Query = pasteFormat.Prompt;
- CustomActionActivated?.Invoke(this, new CustomActionActivatedEventArgs(pasteFormat.Prompt, false));
- break;
+ try
+ {
+ // Minimum time to show busy spinner for AI actions when triggered by global keyboard shortcut.
+ var aiActionMinTaskTime = TimeSpan.FromSeconds(2);
+ var delayTask = (Visible && source == PasteActionSource.GlobalKeyboardShortcut) ? Task.Delay(aiActionMinTaskTime) : Task.CompletedTask;
+ var aiOutput = await _pasteFormatExecutor.ExecutePasteFormatAsync(pasteFormat, source);
+
+ await delayTask;
+
+ if (pasteFormat.Format != PasteFormats.Custom)
+ {
+ HideWindow();
+
+ if (source == PasteActionSource.GlobalKeyboardShortcut || _userSettings.SendPasteKeyCombination)
+ {
+ ClipboardHelper.SendPasteKeyCombination();
+ }
+ }
+ else
+ {
+ var pasteResult = source == PasteActionSource.GlobalKeyboardShortcut || !_userSettings.ShowCustomPreview;
+
+ GeneratedResponses.Add(aiOutput);
+ CurrentResponseIndex = GeneratedResponses.Count - 1;
+ CustomActionActivated?.Invoke(this, new CustomActionActivatedEventArgs(pasteFormat.Prompt, pasteResult));
+
+ if (pasteResult)
+ {
+ PasteCustom();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError("Error executing paste format", ex);
+ PasteOperationErrorText = ex is PasteActionException ? ex.Message : ResourceLoaderInstance.ResourceLoader.GetString("PasteError");
+ }
+
+ Busy = false;
+ }
+
+ internal async Task ExecutePasteFormatAsync(VirtualKey key)
+ {
+ var pasteFormat = StandardPasteFormats.Concat(CustomActionPasteFormats)
+ .Where(pasteFormat => pasteFormat.IsEnabled)
+ .ElementAtOrDefault(key - VirtualKey.Number1);
+
+ if (pasteFormat != null)
+ {
+ await ExecutePasteFormatAsync(pasteFormat, PasteActionSource.InAppKeyboardShortcut);
}
}
- internal void ExecuteCustomActionWithPaste(int customActionId)
+ internal async Task ExecuteCustomActionAsync(int customActionId, PasteActionSource source)
{
Logger.LogTrace();
+ await ReadClipboardAsync();
+
var customAction = _userSettings.CustomActions.FirstOrDefault(customAction => customAction.Id == customActionId);
if (customAction != null)
{
- Query = customAction.Prompt;
- CustomActionActivated?.Invoke(this, new CustomActionActivatedEventArgs(customAction.Prompt, true));
+ await ExecutePasteFormatAsync(CreatePasteFormat(customAction), source);
}
}
- internal async Task GenerateCustomFunction(string inputInstructions)
+ internal async Task GenerateCustomFunctionAsync(PasteActionSource triggerSource)
{
- Logger.LogTrace();
-
- if (string.IsNullOrWhiteSpace(inputInstructions) || !IsCustomAIEnabled)
- {
- return string.Empty;
- }
-
- if (!IsClipboardDataText)
- {
- Logger.LogWarning("Clipboard does not contain text data");
- return string.Empty;
- }
-
- string currentClipboardText = await Task.Run(async () =>
- {
- try
- {
- string text = await ClipboardData.GetTextAsync() as string;
- return text;
- }
- catch (Exception)
- {
- // Couldn't get text from the clipboard. Resume with empty text.
- return string.Empty;
- }
- });
-
- if (string.IsNullOrWhiteSpace(currentClipboardText))
- {
- Logger.LogWarning("Clipboard has no usable text data");
- return string.Empty;
- }
-
- var aiResponse = await Task.Run(() => aiHelper.AIFormatString(inputInstructions, currentClipboardText));
-
- string aiOutput = aiResponse.Response;
- ApiRequestStatus = aiResponse.ApiRequestStatus;
-
- GeneratedResponses.Add(aiOutput);
- CurrentResponseIndex = GeneratedResponses.Count - 1;
- return aiOutput;
+ AdvancedPasteCustomAction customAction = new() { Name = "Default", Prompt = Query };
+ await ExecutePasteFormatAsync(CreatePasteFormat(customAction), triggerSource);
}
- internal void PasteCustomFunction(string text)
+ private void HideWindow()
{
- Logger.LogTrace();
+ var mainWindow = GetMainWindow();
- SetClipboardContentAndHideWindow(text);
-
- if (_userSettings.SendPasteKeyCombination)
+ if (mainWindow != null)
{
- ClipboardHelper.SendPasteKeyCombination();
+ Windows.Win32.Foundation.HWND hwnd = (Windows.Win32.Foundation.HWND)mainWindow.GetWindowHandle();
+ Windows.Win32.PInvoke.ShowWindow(hwnd, Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
}
}
@@ -524,11 +457,7 @@ namespace AdvancedPaste.ViewModels
return;
}
- string currentClipboardText = Task.Run(async () =>
- {
- string text = await clipboardData.GetTextAsync() as string;
- return text;
- }).Result;
+ var currentClipboardText = Task.Run(async () => await clipboardData.GetTextAsync()).Result;
var queryData = new CustomQuery
{
@@ -536,13 +465,13 @@ namespace AdvancedPaste.ViewModels
ClipboardData = currentClipboardText,
};
- SettingsUtils utils = new SettingsUtils();
+ SettingsUtils utils = new();
utils.SaveSettings(queryData.ToString(), Constants.AdvancedPasteModuleName, Constants.LastQueryJsonFileName);
}
internal CustomQuery LoadPreviousQuery()
{
- SettingsUtils utils = new SettingsUtils();
+ SettingsUtils utils = new();
var query = utils.GetSettings(Constants.AdvancedPasteModuleName, Constants.LastQueryJsonFileName);
return query;
}
@@ -572,9 +501,9 @@ namespace AdvancedPaste.ViewModels
if (IsAllowedByGPO)
{
- var oldKey = aiHelper.GetKey();
+ var oldKey = _aiHelper.GetKey();
var newKey = AICompletionsHelper.LoadOpenAIKey();
- aiHelper.SetOpenAIKey(newKey);
+ _aiHelper.SetOpenAIKey(newKey);
return newKey != oldKey;
}
diff --git a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp
index 649342bc2f..8bd2e0860e 100644
--- a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp
+++ b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp
@@ -42,6 +42,7 @@ namespace
{
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_CUSTOM_ACTIONS[] = L"custom-actions";
+ const wchar_t JSON_KEY_ADDITIONAL_ACTIONS[] = L"additional-actions";
const wchar_t JSON_KEY_SHORTCUT[] = L"shortcut";
const wchar_t JSON_KEY_IS_SHOWN[] = L"isShown";
const wchar_t JSON_KEY_ID[] = L"id";
@@ -73,7 +74,6 @@ private:
HANDLE m_hProcess;
- std::thread create_pipe_thread;
std::unique_ptr m_write_pipe;
// Time to wait for process to close after sending WM_CLOSE signal
@@ -86,8 +86,18 @@ private:
Hotkey m_paste_as_markdown_hotkey{};
Hotkey m_paste_as_json_hotkey{};
- std::vector m_custom_action_hotkeys;
- std::vector m_custom_action_ids;
+ template
+ struct ActionData
+ {
+ Id id;
+ Hotkey hotkey;
+ };
+
+ using AdditionalAction = ActionData;
+ std::vector m_additional_actions;
+
+ using CustomAction = ActionData;
+ std::vector m_custom_actions;
bool m_preview_custom_format_output = true;
@@ -166,6 +176,34 @@ private:
open_ai_key_exists();
}
+ static std::wstring kebab_to_pascal_case(const std::wstring& kebab_str)
+ {
+ std::wstring result;
+ bool capitalize_next = true;
+
+ for (const auto ch : kebab_str)
+ {
+ if (ch == L'-')
+ {
+ capitalize_next = true;
+ }
+ else
+ {
+ if (capitalize_next)
+ {
+ result += std::towupper(ch);
+ capitalize_next = false;
+ }
+ else
+ {
+ result += ch;
+ }
+ }
+ }
+
+ return result;
+ }
+
bool migrate_data_and_remove_data_file(Hotkey& old_paste_as_plain_hotkey)
{
const wchar_t OLD_JSON_KEY_ACTIVATION_SHORTCUT[] = L"ActivationShortcut";
@@ -197,6 +235,39 @@ private:
return false;
}
+ void process_additional_action(const winrt::hstring& actionName, const winrt::Windows::Data::Json::IJsonValue& actionValue)
+ {
+ if (actionValue.ValueType() != winrt::Windows::Data::Json::JsonValueType::Object)
+ {
+ return;
+ }
+
+ const auto action = actionValue.GetObjectW();
+
+ if (!action.GetNamedBoolean(JSON_KEY_IS_SHOWN, false))
+ {
+ return;
+ }
+
+ if (action.HasKey(JSON_KEY_SHORTCUT))
+ {
+ const AdditionalAction additionalAction
+ {
+ actionName.c_str(),
+ parse_single_hotkey(action.GetNamedObject(JSON_KEY_SHORTCUT))
+ };
+
+ m_additional_actions.push_back(additionalAction);
+ }
+ else
+ {
+ for (const auto& [subActionName, subAction] : action)
+ {
+ process_additional_action(subActionName, subAction);
+ }
+ }
+ }
+
void parse_hotkeys(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -239,13 +310,23 @@ private:
*hotkey = parse_single_hotkey(keyName, settingsObject);
}
- m_custom_action_hotkeys.clear();
- m_custom_action_ids.clear();
+ m_additional_actions.clear();
+ m_custom_actions.clear();
if (settingsObject.HasKey(JSON_KEY_PROPERTIES))
{
const auto propertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES);
+ if (propertiesObject.HasKey(JSON_KEY_ADDITIONAL_ACTIONS))
+ {
+ const auto additionalActions = propertiesObject.GetNamedObject(JSON_KEY_ADDITIONAL_ACTIONS);
+
+ for (const auto& [actionName, additionalAction] : additionalActions)
+ {
+ process_additional_action(actionName, additionalAction);
+ }
+ }
+
if (propertiesObject.HasKey(JSON_KEY_CUSTOM_ACTIONS))
{
const auto customActions = propertiesObject.GetNamedObject(JSON_KEY_CUSTOM_ACTIONS).GetNamedArray(JSON_KEY_VALUE);
@@ -257,8 +338,13 @@ private:
if (object.GetNamedBoolean(JSON_KEY_IS_SHOWN, false))
{
- m_custom_action_hotkeys.push_back(parse_single_hotkey(object.GetNamedObject(JSON_KEY_SHORTCUT)));
- m_custom_action_ids.push_back(static_cast(object.GetNamedNumber(JSON_KEY_ID)));
+ const CustomAction customActionData
+ {
+ static_cast(object.GetNamedNumber(JSON_KEY_ID)),
+ parse_single_hotkey(object.GetNamedObject(JSON_KEY_SHORTCUT))
+ };
+
+ m_custom_actions.push_back(customActionData);
}
}
}
@@ -298,7 +384,6 @@ private:
m_hProcess = sei.hProcess;
}
-
std::optional get_pipe_name(const std::wstring& prefix) const
{
UUID temp_uuid;
@@ -331,7 +416,7 @@ private:
return;
}
- create_pipe_thread = std::thread([&] { start_named_pipe_server(pipe_name.value()); });
+ std::thread create_pipe_thread ([&]{ start_named_pipe_server(pipe_name.value()); });
launch_process(pipe_name.value());
create_pipe_thread.join();
}
@@ -675,6 +760,8 @@ public:
// Destroy the powertoy and free memory
virtual void destroy() override
{
+ Disable(false);
+
Logger::trace("AdvancedPaste::destroy()");
delete this;
}
@@ -730,12 +817,19 @@ public:
m_preview_custom_format_output = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHOW_CUSTOM_PREVIEW).GetNamedBoolean(JSON_KEY_VALUE);
}
+ std::unordered_map additionalActionMap;
+ for (const auto& action : m_additional_actions)
+ {
+ additionalActionMap[kebab_to_pascal_case(action.id)] = action.hotkey;
+ }
+
// order of args matter
Trace::AdvancedPaste_SettingsTelemetry(m_paste_as_plain_hotkey,
m_advanced_paste_ui_hotkey,
m_paste_as_markdown_hotkey,
m_paste_as_json_hotkey,
- m_preview_custom_format_output);
+ m_preview_custom_format_output,
+ additionalActionMap);
// If you don't need to do any custom processing of the settings, proceed
// to persists the values calling:
@@ -758,15 +852,21 @@ public:
launch_process_and_named_pipe();
};
- virtual void disable()
+ void Disable(bool traceEvent)
{
- Logger::trace("AdvancedPaste::disable()");
if (m_enabled)
{
+ send_named_pipe_message(CommonSharedConstants::ADVANCED_PASTE_TERMINATE_APP_MESSAGE);
+ WaitForSingleObject(m_hProcess, 1500);
+
m_write_pipe = nullptr;
TerminateProcess(m_hProcess, 1);
- Trace::AdvancedPaste_Enable(false);
+
+ if (traceEvent)
+ {
+ Trace::AdvancedPaste_Enable(false);
+ }
CloseHandle(m_hProcess);
m_hProcess = 0;
@@ -775,6 +875,12 @@ public:
m_enabled = false;
}
+ virtual void disable()
+ {
+ Logger::trace("AdvancedPaste::disable()");
+ Disable(true);
+ }
+
virtual bool on_hotkey(size_t hotkeyId) override
{
Logger::trace(L"AdvancedPaste hotkey pressed");
@@ -825,11 +931,24 @@ public:
return true;
}
- const auto custom_action_index = hotkeyId - NUM_DEFAULT_HOTKEYS;
- if (custom_action_index < m_custom_action_ids.size())
+ const auto additional_action_index = hotkeyId - NUM_DEFAULT_HOTKEYS;
+ if (additional_action_index < m_additional_actions.size())
{
- const auto id = m_custom_action_ids.at(custom_action_index);
+ const auto& id = m_additional_actions.at(additional_action_index).id;
+
+ Logger::trace(L"Starting additional action id={}", id);
+
+ Trace::AdvancedPaste_Invoked(std::format(L"{}Direct", kebab_to_pascal_case(id)));
+
+ send_named_pipe_message(CommonSharedConstants::ADVANCED_PASTE_ADDITIONAL_ACTION_MESSAGE, id);
+ return true;
+ }
+
+ const auto custom_action_index = additional_action_index - m_additional_actions.size();
+ if (custom_action_index < m_custom_actions.size())
+ {
+ const auto id = m_custom_actions.at(custom_action_index).id;
Logger::trace(L"Starting custom action id={}", id);
@@ -844,7 +963,7 @@ public:
virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
{
- const size_t num_hotkeys = NUM_DEFAULT_HOTKEYS + m_custom_action_hotkeys.size();
+ const size_t num_hotkeys = NUM_DEFAULT_HOTKEYS + m_additional_actions.size() + m_custom_actions.size();
if (hotkeys && buffer_size >= num_hotkeys)
{
@@ -852,9 +971,11 @@ public:
m_advanced_paste_ui_hotkey,
m_paste_as_markdown_hotkey,
m_paste_as_json_hotkey };
-
std::copy(default_hotkeys.begin(), default_hotkeys.end(), hotkeys);
- std::copy(m_custom_action_hotkeys.begin(), m_custom_action_hotkeys.end(), hotkeys + NUM_DEFAULT_HOTKEYS);
+
+ const auto get_action_hotkey = [](const auto& action) { return action.hotkey; };
+ std::transform(m_additional_actions.begin(), m_additional_actions.end(), hotkeys + NUM_DEFAULT_HOTKEYS, get_action_hotkey);
+ std::transform(m_custom_actions.begin(), m_custom_actions.end(), hotkeys + NUM_DEFAULT_HOTKEYS + m_additional_actions.size(), get_action_hotkey);
}
return num_hotkeys;
diff --git a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/pch.h b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/pch.h
index 809b965271..e730ab2036 100644
--- a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/pch.h
+++ b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/pch.h
@@ -2,7 +2,6 @@
#include
#include
#include
-#include
#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.cpp b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.cpp
index 87d610682f..aa6162c465 100644
--- a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.cpp
+++ b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.cpp
@@ -8,20 +8,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has AdvancedPaste enabled or disabled
void Trace::AdvancedPaste_Enable(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"AdvancedPaste_EnableAdvancedPaste",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +22,7 @@ void Trace::AdvancedPaste_Enable(const bool enabled) noexcept
// Log if the user has invoked AdvancedPaste
void Trace::AdvancedPaste_Invoked(std::wstring mode) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"AdvancedPaste_InvokeAdvancedPaste",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -43,7 +33,7 @@ void Trace::AdvancedPaste_Invoked(std::wstring mode) noexcept
// Log if an error occurs in AdvancedPaste
void Trace::AdvancedPaste_Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"AdvancedPaste_Error",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -58,45 +48,44 @@ void Trace::AdvancedPaste_SettingsTelemetry(const PowertoyModuleIface::Hotkey& p
const PowertoyModuleIface::Hotkey& advancedPasteUIHotkey,
const PowertoyModuleIface::Hotkey& pasteMarkdownHotkey,
const PowertoyModuleIface::Hotkey& pasteJsonHotkey,
- const bool preview_custom_format_output) noexcept
+ const bool preview_custom_format_output,
+ const std::unordered_map& additionalActionsHotkeys) noexcept
{
- std::wstring pastePlainHotkeyStr =
- std::wstring(pastePlainHotkey.win ? L"Win + " : L"") +
- std::wstring(pastePlainHotkey.ctrl ? L"Ctrl + " : L"") +
- std::wstring(pastePlainHotkey.shift ? L"Shift + " : L"") +
- std::wstring(pastePlainHotkey.alt ? L"Alt + " : L"") +
- std::wstring(L"VK ") + std::to_wstring(pastePlainHotkey.key);
+ const auto getHotKeyStr = [](const PowertoyModuleIface::Hotkey& hotKey)
+ {
+ return std::wstring(hotKey.win ? L"Win + " : L"") +
+ std::wstring(hotKey.ctrl ? L"Ctrl + " : L"") +
+ std::wstring(hotKey.shift ? L"Shift + " : L"") +
+ std::wstring(hotKey.alt ? L"Alt + " : L"") +
+ std::wstring(L"VK ") + std::to_wstring(hotKey.key);
+ };
- std::wstring advancedPasteUIHotkeyStr =
- std::wstring(advancedPasteUIHotkey.win ? L"Win + " : L"") +
- std::wstring(advancedPasteUIHotkey.ctrl ? L"Ctrl + " : L"") +
- std::wstring(advancedPasteUIHotkey.shift ? L"Shift + " : L"") +
- std::wstring(advancedPasteUIHotkey.alt ? L"Alt + " : L"") +
- std::wstring(L"VK ") + std::to_wstring(advancedPasteUIHotkey.key);
+ std::vector hotkeyStrs;
+ const auto getHotkeyCStr = [&](const PowertoyModuleIface::Hotkey& hotkey)
+ {
+ hotkeyStrs.push_back(getHotKeyStr(hotkey)); // Probably unnecessary, but offers protection against the macro TraceLoggingWideString expanding to something that would invalidate the pointer
+ return hotkeyStrs.back().c_str();
+ };
- std::wstring pasteMarkdownHotkeyStr =
- std::wstring(pasteMarkdownHotkey.win ? L"Win + " : L"") +
- std::wstring(pasteMarkdownHotkey.ctrl ? L"Ctrl + " : L"") +
- std::wstring(pasteMarkdownHotkey.shift ? L"Shift + " : L"") +
- std::wstring(pasteMarkdownHotkey.alt ? L"Alt + " : L"") +
- std::wstring(L"VK ") + std::to_wstring(pasteMarkdownHotkey.key);
+ const auto getAdditionalActionHotkeyCStr = [&](const std::wstring& name)
+ {
+ const auto it = additionalActionsHotkeys.find(name);
+ return it != additionalActionsHotkeys.end() ? getHotkeyCStr(it->second) : L"";
+ };
- std::wstring pasteJsonHotkeyStr =
- std::wstring(pasteJsonHotkey.win ? L"Win + " : L"") +
- std::wstring(pasteJsonHotkey.ctrl ? L"Ctrl + " : L"") +
- std::wstring(pasteJsonHotkey.shift ? L"Shift + " : L"") +
- std::wstring(pasteJsonHotkey.alt ? L"Alt + " : L"") +
- std::wstring(L"VK ") + std::to_wstring(pasteJsonHotkey.key);
-
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"AdvancedPaste_Settings",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
- TraceLoggingWideString(pastePlainHotkeyStr.c_str(), "PastePlainHotkey"),
- TraceLoggingWideString(advancedPasteUIHotkeyStr.c_str(), "AdvancedPasteUIHotkey"),
- TraceLoggingWideString(pasteMarkdownHotkeyStr.c_str(), "PasteMarkdownHotkey"),
- TraceLoggingWideString(pasteJsonHotkeyStr.c_str(), "PasteJsonHotkey"),
- TraceLoggingBoolean(preview_custom_format_output, "ShowCustomPreview")
+ TraceLoggingWideString(getHotkeyCStr(pastePlainHotkey), "PastePlainHotkey"),
+ TraceLoggingWideString(getHotkeyCStr(advancedPasteUIHotkey), "AdvancedPasteUIHotkey"),
+ TraceLoggingWideString(getHotkeyCStr(pasteMarkdownHotkey), "PasteMarkdownHotkey"),
+ TraceLoggingWideString(getHotkeyCStr(pasteJsonHotkey), "PasteJsonHotkey"),
+ TraceLoggingBoolean(preview_custom_format_output, "ShowCustomPreview"),
+ TraceLoggingWideString(getAdditionalActionHotkeyCStr(L"ImageToText"), "ImageToTextHotkey"),
+ TraceLoggingWideString(getAdditionalActionHotkeyCStr(L"PasteAsTxtFile"), "PasteAsTxtFileHotkey"),
+ TraceLoggingWideString(getAdditionalActionHotkeyCStr(L"PasteAsPngFile"), "PasteAsPngFileHotkey"),
+ TraceLoggingWideString(getAdditionalActionHotkeyCStr(L"PasteAsHtmlFile"), "PasteAsHtmlFileHotkey")
);
}
diff --git a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.h b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.h
index d64d1cd874..c7cee38877 100644
--- a/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.h
+++ b/src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.h
@@ -1,12 +1,11 @@
#pragma once
+#include
#include
+#include
-class Trace
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
// Log if the user has AdvancedPaste enabled or disabled
static void AdvancedPaste_Enable(const bool enabled) noexcept;
@@ -21,5 +20,6 @@ public:
const PowertoyModuleIface::Hotkey& advancedPasteUIHotkey,
const PowertoyModuleIface::Hotkey& pasteMarkdownHotkey,
const PowertoyModuleIface::Hotkey& pasteJsonHotkey,
- const bool preview_custom_format_output) noexcept;
+ const bool preview_custom_format_output,
+ const std::unordered_map& additionalActionsHotkeys) noexcept;
};
diff --git a/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj b/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj
index 0f6c2bb1d1..89177bd56f 100644
--- a/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj
+++ b/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj
@@ -151,6 +151,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
diff --git a/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj.filters b/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj.filters
index 98752f066d..bea68db119 100644
--- a/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj.filters
+++ b/src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj.filters
@@ -27,6 +27,7 @@
+
diff --git a/src/modules/CropAndLock/CropAndLock/main.cpp b/src/modules/CropAndLock/CropAndLock/main.cpp
index dc530b7769..79d26fc8c1 100644
--- a/src/modules/CropAndLock/CropAndLock/main.cpp
+++ b/src/modules/CropAndLock/CropAndLock/main.cpp
@@ -4,16 +4,20 @@
#include "CropAndLockWindow.h"
#include "ThumbnailCropAndLockWindow.h"
#include "ReparentCropAndLockWindow.h"
-#include
-#include
-#include
-#include
-#include
#include "ModuleConstants.h"
-#include
#include "trace.h"
-#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
namespace winrt
{
@@ -36,6 +40,11 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
// Initialize COM
winrt::init_apartment(winrt::apartment_type::single_threaded);
+ Trace::CropAndLock::RegisterProvider();
+
+ Shared::Trace::ETWTrace trace;
+ trace.UpdateState(true);
+
// Initialize logger automatic logging of exceptions.
LoggerHelpers::init_logger(NonLocalizable::ModuleKey, L"", LogSettings::cropAndLockLoggerName);
InitUnhandledExceptionHandler();
@@ -107,8 +116,7 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
HANDLE m_exit_event_handle;
std::thread m_event_triggers_thread;
- std::function removeWindowCallback = [&](HWND windowHandle)
- {
+ std::function removeWindowCallback = [&](HWND windowHandle) {
if (!m_running)
{
// If we're not running, the reference to croppedWindows might no longer be valid and cause a crash at exit time, due to being called by destructors after wWinMain returns.
@@ -122,8 +130,7 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
}
};
- std::function ProcessCommand = [&](CropAndLockType mode)
- {
+ std::function ProcessCommand = [&](CropAndLockType mode) {
std::function windowCroppedCallback = [&, mode](HWND targetWindow, RECT cropRect) {
auto targetInfo = util::WindowInfo(targetWindow);
// TODO: Fix WindowInfo.h to not contain the null char at the end.
@@ -196,7 +203,7 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
m_event_triggers_thread = std::thread([&]() {
MSG msg;
- HANDLE event_handles[3] = {m_reparent_event_handle, m_thumbnail_event_handle, m_exit_event_handle};
+ HANDLE event_handles[3] = { m_reparent_event_handle, m_thumbnail_event_handle, m_exit_event_handle };
while (m_running)
{
DWORD dwEvt = MsgWaitForMultipleObjects(3, event_handles, false, INFINITE, QS_ALLINPUT);
@@ -258,6 +265,10 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
DispatchMessageW(&msg);
}
+ trace.Flush();
+
+ Trace::CropAndLock::UnregisterProvider();
+
m_running = false;
// Needed to unblock MsgWaitForMultipleObjects one last time
SetEvent(m_reparent_event_handle);
diff --git a/src/modules/CropAndLock/CropAndLock/pch.h b/src/modules/CropAndLock/CropAndLock/pch.h
index 720033cbca..75bb5f4a61 100644
--- a/src/modules/CropAndLock/CropAndLock/pch.h
+++ b/src/modules/CropAndLock/CropAndLock/pch.h
@@ -74,7 +74,6 @@
#include "WindowRectUtil.h"
// PowerToys
-#include
#include
// Application resources
diff --git a/src/modules/CropAndLock/CropAndLock/trace.cpp b/src/modules/CropAndLock/CropAndLock/trace.cpp
index fb5dd802c5..42674ec624 100644
--- a/src/modules/CropAndLock/CropAndLock/trace.cpp
+++ b/src/modules/CropAndLock/CropAndLock/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
// Telemetry strings should not be localized.
#define LoggingProviderKey "Microsoft.PowerToys"
@@ -11,19 +13,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::CropAndLock::Enable(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_EnableCropAndLock",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -33,7 +25,7 @@ void Trace::CropAndLock::Enable(bool enabled) noexcept
void Trace::CropAndLock::ActivateReparent() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_ActivateReparent",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -42,7 +34,7 @@ void Trace::CropAndLock::ActivateReparent() noexcept
void Trace::CropAndLock::ActivateThumbnail() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_ActivateThumbnail",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -51,7 +43,7 @@ void Trace::CropAndLock::ActivateThumbnail() noexcept
void Trace::CropAndLock::CreateReparentWindow() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_CreateReparentWindow",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -60,7 +52,7 @@ void Trace::CropAndLock::CreateReparentWindow() noexcept
void Trace::CropAndLock::CreateThumbnailWindow() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_CreateThumbnailWindow",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -84,12 +76,11 @@ void Trace::CropAndLock::SettingsTelemetry(PowertoyModuleIface::Hotkey& reparent
std::wstring(thumbnailHotkey.alt ? L"Alt + " : L"") +
std::wstring(L"VK ") + std::to_wstring(thumbnailHotkey.key);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CropAndLock_Settings",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingWideString(hotKeyStrReparent.c_str(), "ReparentHotKey"),
- TraceLoggingWideString(hotKeyStrThumbnail.c_str(), "ThumbnailHotkey")
- );
+ TraceLoggingWideString(hotKeyStrThumbnail.c_str(), "ThumbnailHotkey"));
}
diff --git a/src/modules/CropAndLock/CropAndLock/trace.h b/src/modules/CropAndLock/CropAndLock/trace.h
index f7e1903ee6..5a9aaa95ca 100644
--- a/src/modules/CropAndLock/CropAndLock/trace.h
+++ b/src/modules/CropAndLock/CropAndLock/trace.h
@@ -1,13 +1,12 @@
#pragma once
+
+#include
#include
class Trace
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
- class CropAndLock
+ class CropAndLock : public telemetry::TraceBase
{
public:
static void Enable(bool enabled) noexcept;
diff --git a/src/modules/CropAndLock/CropAndLockModuleInterface/dllmain.cpp b/src/modules/CropAndLock/CropAndLockModuleInterface/dllmain.cpp
index c313d63cd7..42c7c6da7e 100644
--- a/src/modules/CropAndLock/CropAndLockModuleInterface/dllmain.cpp
+++ b/src/modules/CropAndLock/CropAndLockModuleInterface/dllmain.cpp
@@ -40,13 +40,13 @@ BOOL APIENTRY DllMain( HMODULE /*hModule*/,
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
- Trace::RegisterProvider();
+ Trace::CropAndLock::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
- Trace::UnregisterProvider();
+ Trace::CropAndLock::UnregisterProvider();
break;
}
return TRUE;
diff --git a/src/modules/CropAndLock/CropAndLockModuleInterface/pch.h b/src/modules/CropAndLock/CropAndLockModuleInterface/pch.h
index 0df2e08a6f..3914e22561 100644
--- a/src/modules/CropAndLock/CropAndLockModuleInterface/pch.h
+++ b/src/modules/CropAndLock/CropAndLockModuleInterface/pch.h
@@ -6,7 +6,5 @@
#include
#include
#include
-#include
-#include
#include
#include
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/App.xaml.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/App.xaml.cs
index bc6f5aa1da..e40478f222 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/App.xaml.cs
+++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/App.xaml.cs
@@ -26,6 +26,8 @@ namespace EnvironmentVariables
{
public IHost Host { get; }
+ public ETWTrace EtwTrace { get; } = new ETWTrace();
+
public static T GetService()
where T : class
{
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml
index 78d46d85c7..32c536101e 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml
+++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml
@@ -1,4 +1,4 @@
-
+
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs
index 7a67a1dfbf..891fadfe1d 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs
+++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs
@@ -88,5 +88,10 @@ namespace EnvironmentVariables
return NativeMethods.CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
}
+
+ private void Window_Closed(object sender, WindowEventArgs args)
+ {
+ (App.Current as EnvironmentVariables.App).EtwTrace?.Dispose();
+ }
}
}
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/pch.h b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/pch.h
index 6f70098567..308dff2b3a 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/pch.h
+++ b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/pch.h
@@ -10,7 +10,6 @@
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include
-#include
#include
#include
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.cpp b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.cpp
index bb458c1b6d..6cb84aed08 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.cpp
+++ b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has Environment Variables enabled or disabled
void Trace::EnableEnvironmentVariables(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"EnvironmentVariables_EnableEnvironmentVariables",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +24,7 @@ void Trace::EnableEnvironmentVariables(const bool enabled) noexcept
// Log that the user tried to activate the editor
void Trace::ActivateEnvironmentVariables() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"EnvironmentVariables_Activate",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.h b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.h
index 0898da4602..fa37b043b5 100644
--- a/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.h
+++ b/src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log if the user has EnvironmentVariables enabled or disabled
static void EnableEnvironmentVariables(const bool enabled) noexcept;
diff --git a/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj b/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj
index ac0580c2a0..10478cd30c 100644
--- a/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj
+++ b/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj
@@ -128,6 +128,9 @@ MakeAppx.exe pack /d . /p $(OutDir)FileLocksmithContextMenuPackage.msix /nv
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}
diff --git a/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj.filters b/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj.filters
index 5ec8585829..6646b4fc10 100644
--- a/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj.filters
+++ b/src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj.filters
@@ -1,5 +1,6 @@
-
+
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
diff --git a/src/modules/FileLocksmith/FileLocksmithContextMenu/dllmain.cpp b/src/modules/FileLocksmith/FileLocksmithContextMenu/dllmain.cpp
index 1abf0e947b..a597b9ca80 100644
--- a/src/modules/FileLocksmith/FileLocksmithContextMenu/dllmain.cpp
+++ b/src/modules/FileLocksmith/FileLocksmithContextMenu/dllmain.cpp
@@ -1,6 +1,7 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
+#include
#include
#include
#include
@@ -20,6 +21,7 @@
using namespace Microsoft::WRL;
HINSTANCE g_hInst = 0;
+Shared::Trace::ETWTrace trace(L"FileLocksmithContextMenu");
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
@@ -91,6 +93,8 @@ public:
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
{
+ trace.UpdateState(true);
+
Trace::Invoked();
ipc::Writer writer;
@@ -102,6 +106,9 @@ public:
if (HRESULT result = writer.start(); FAILED(result))
{
Trace::InvokedRet(result);
+
+ trace.Flush();
+ trace.UpdateState(false);
return result;
}
@@ -114,6 +121,10 @@ public:
{
result = E_FAIL;
Trace::InvokedRet(result);
+
+ trace.Flush();
+ trace.UpdateState(false);
+
return result;
}
@@ -140,6 +151,10 @@ public:
}
Trace::InvokedRet(S_OK);
+
+ trace.Flush();
+ trace.UpdateState(false);
+
return S_OK;
}
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
index bc4ab945ca..49e2e67c19 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
+++ b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
@@ -152,8 +152,13 @@ IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UI
if (!InsertMenuItem(hmenu, indexMenu, TRUE, &mii))
{
+ m_etwTrace.UpdateState(true);
+
hr = HRESULT_FROM_WIN32(GetLastError());
Trace::QueryContextMenuError(hr);
+
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
}
else
{
@@ -166,6 +171,8 @@ IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UI
IFACEMETHODIMP ExplorerCommand::InvokeCommand(CMINVOKECOMMANDINFO* pici)
{
+ m_etwTrace.UpdateState(true);
+
HRESULT hr = E_FAIL;
if (FileLocksmithSettingsInstance().GetEnabled() &&
@@ -178,12 +185,16 @@ IFACEMETHODIMP ExplorerCommand::InvokeCommand(CMINVOKECOMMANDINFO* pici)
if (HRESULT result = writer.start(); FAILED(result))
{
Trace::InvokedRet(result);
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
return result;
}
if (HRESULT result = LaunchUI(pici, &writer); FAILED(result))
{
Trace::InvokedRet(result);
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
return result;
}
@@ -217,6 +228,9 @@ IFACEMETHODIMP ExplorerCommand::InvokeCommand(CMINVOKECOMMANDINFO* pici)
}
Trace::InvokedRet(hr);
+
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
return hr;
}
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
index d59f266157..143b6afd9f 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
+++ b/src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
@@ -4,6 +4,8 @@
#include "FileLocksmithLib/IPC.h"
+#include
+
#define EXPLORER_COMMAND_UUID_STR "84d68575-e186-46ad-b0cb-baeb45ee29c0"
class __declspec(uuid(EXPLORER_COMMAND_UUID_STR)) ExplorerCommand : public IExplorerCommand, public IShellExtInit, public IContextMenu
@@ -50,4 +52,6 @@ private:
std::atomic m_ref_count = 1;
IDataObject* m_data_obj = NULL;
std::wstring context_menu_caption;
+
+ Shared::Trace::ETWTrace m_etwTrace{ L"FileExplorerExt" };
};
diff --git a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
index 9bfad7f8a8..0c285a8bfa 100644
--- a/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
+++ b/src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj
@@ -103,6 +103,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/FileLocksmith/FileLocksmithLib/Trace.cpp b/src/modules/FileLocksmith/FileLocksmithLib/Trace.cpp
index 98b2f9985d..a3d8e9038e 100644
--- a/src/modules/FileLocksmith/FileLocksmithLib/Trace.cpp
+++ b/src/modules/FileLocksmith/FileLocksmithLib/Trace.cpp
@@ -1,7 +1,8 @@
#include "pch.h"
#include "Trace.h"
-#include "../common/Telemetry/ProjectTelemetry.h"
+
+#include
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
@@ -10,19 +11,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::EnableFileLocksmith(_In_ bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FileLocksmith_EnableFileLocksmith",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +23,7 @@ void Trace::EnableFileLocksmith(_In_ bool enabled) noexcept
void Trace::Invoked() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FileLocksmith_Invoked",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -41,7 +32,7 @@ void Trace::Invoked() noexcept
void Trace::InvokedRet(_In_ HRESULT hr) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FileLocksmith_InvokedRet",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -51,7 +42,7 @@ void Trace::InvokedRet(_In_ HRESULT hr) noexcept
void Trace::QueryContextMenuError(_In_ HRESULT hr) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FileLocksmith_QueryContextMenuError",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/FileLocksmith/FileLocksmithLib/Trace.h b/src/modules/FileLocksmith/FileLocksmithLib/Trace.h
index a9516b5d5c..98642de854 100644
--- a/src/modules/FileLocksmith/FileLocksmithLib/Trace.h
+++ b/src/modules/FileLocksmith/FileLocksmithLib/Trace.h
@@ -2,11 +2,11 @@
#include "pch.h"
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
static void EnableFileLocksmith(_In_ bool enabled) noexcept;
static void Invoked() noexcept;
static void InvokedRet(_In_ HRESULT hr) noexcept;
diff --git a/src/modules/Hosts/Hosts/Helpers/NativeEventWaiter.cs b/src/modules/Hosts/Hosts/Helpers/NativeEventWaiter.cs
new file mode 100644
index 0000000000..b63468d553
--- /dev/null
+++ b/src/modules/Hosts/Hosts/Helpers/NativeEventWaiter.cs
@@ -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;
+using System.Threading;
+
+using Microsoft.UI.Dispatching;
+
+namespace Hosts.Helpers
+{
+ public static class NativeEventWaiter
+ {
+ public static void WaitForEventLoop(string eventName, Action callback)
+ {
+ var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
+ new Thread(() =>
+ {
+ var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
+ while (true)
+ {
+ if (eventHandle.WaitOne())
+ {
+ dispatcherQueue.TryEnqueue(() => callback());
+ }
+ }
+ }).Start();
+ }
+ }
+}
diff --git a/src/modules/Hosts/Hosts/HostsXAML/App.xaml.cs b/src/modules/Hosts/Hosts/HostsXAML/App.xaml.cs
index cd4d8b177f..7c4d6c389e 100644
--- a/src/modules/Hosts/Hosts/HostsXAML/App.xaml.cs
+++ b/src/modules/Hosts/Hosts/HostsXAML/App.xaml.cs
@@ -17,7 +17,7 @@ using Microsoft.Extensions.Hosting;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
-
+using PowerToys.Interop;
using static HostsUILib.Settings.IUserSettings;
using Host = Hosts.Helpers.Host;
@@ -93,6 +93,12 @@ namespace Hosts
cleanupBackupThread.Start();
UnhandledException += App_UnhandledException;
+
+ Hosts.Helpers.NativeEventWaiter.WaitForEventLoop(Constants.TerminateHostsSharedEvent(), () =>
+ {
+ EtwTrace?.Dispose();
+ Environment.Exit(0);
+ });
}
///
@@ -112,6 +118,7 @@ namespace Hosts
RunnerHelper.WaitForPowerToysRunner(powerToysRunnerPid, () =>
{
Logger.LogInfo("PowerToys Runner exited. Exiting Hosts");
+ EtwTrace?.Dispose();
dispatcher.TryEnqueue(App.Current.Exit);
});
}
@@ -133,5 +140,7 @@ namespace Hosts
}
private Window window;
+
+ public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
}
}
diff --git a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml
index c1229b2ec3..73a883f68b 100644
--- a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml
+++ b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs
index 3f8c01de83..d1632c21ee 100644
--- a/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs
+++ b/src/modules/Hosts/Hosts/HostsXAML/MainWindow.xaml.cs
@@ -62,5 +62,10 @@ namespace Hosts
MainGrid.Children.Add(MainPage);
Grid.SetRow(MainPage, 1);
}
+
+ private void WindowEx_Closed(object sender, WindowEventArgs args)
+ {
+ (Application.Current as App).EtwTrace?.Dispose();
+ }
}
}
diff --git a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp b/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
index 85077c8dbe..807c0829c3 100644
--- a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
+++ b/src/modules/Hosts/HostsModuleInterface/dllmain.cpp
@@ -55,6 +55,8 @@ private:
HANDLE m_hShowAdminEvent{};
+ HANDLE m_hTerminateEvent{};
+
bool is_process_running()
{
return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
@@ -142,6 +144,17 @@ public:
}
}
+ m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_HOSTS_EVENT);
+ if (!m_hTerminateEvent)
+ {
+ Logger::error(L"Failed to create terminate hosts event");
+ auto message = get_last_error_message(GetLastError());
+ if (message.has_value())
+ {
+ Logger::error(message.value());
+ }
+ }
+
m_showEventWaiter = EventWaiter(CommonSharedConstants::SHOW_HOSTS_EVENT, [&](int err)
{
if (m_enabled && err == ERROR_SUCCESS)
@@ -264,6 +277,8 @@ public:
ResetEvent(m_hShowAdminEvent);
}
+ SetEvent(m_hTerminateEvent);
+ WaitForSingleObject(m_hProcess, 1500);
TerminateProcess(m_hProcess, 1);
}
diff --git a/src/modules/Hosts/HostsModuleInterface/pch.h b/src/modules/Hosts/HostsModuleInterface/pch.h
index 7c6ad2a235..5cb4cbf823 100644
--- a/src/modules/Hosts/HostsModuleInterface/pch.h
+++ b/src/modules/Hosts/HostsModuleInterface/pch.h
@@ -2,4 +2,3 @@
#define WIN32_LEAN_AND_MEAN
#include
-#include
\ No newline at end of file
diff --git a/src/modules/Hosts/HostsModuleInterface/trace.cpp b/src/modules/Hosts/HostsModuleInterface/trace.cpp
index 391917a8f2..104075a829 100644
--- a/src/modules/Hosts/HostsModuleInterface/trace.cpp
+++ b/src/modules/Hosts/HostsModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has HostsFileEditor enabled or disabled
void Trace::EnableHostsFileEditor(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"HostsFileEditor_EnableHostsFileEditor",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +24,7 @@ void Trace::EnableHostsFileEditor(const bool enabled) noexcept
// Log that the user tried to activate the editor
void Trace::ActivateEditor() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"HostsFileEditor_Activate",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/Hosts/HostsModuleInterface/trace.h b/src/modules/Hosts/HostsModuleInterface/trace.h
index 92132b7f54..f3dc6310b5 100644
--- a/src/modules/Hosts/HostsModuleInterface/trace.h
+++ b/src/modules/Hosts/HostsModuleInterface/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log if the user has HostsFileEditor enabled or disabled
static void EnableHostsFileEditor(const bool enabled) noexcept;
diff --git a/src/modules/Hosts/HostsUILib/HostsMainPage.xaml.cs b/src/modules/Hosts/HostsUILib/HostsMainPage.xaml.cs
index 8f3303c5ca..197fab4a3b 100644
--- a/src/modules/Hosts/HostsUILib/HostsMainPage.xaml.cs
+++ b/src/modules/Hosts/HostsUILib/HostsMainPage.xaml.cs
@@ -32,7 +32,7 @@ namespace HostsUILib.Views
public ICommand UpdateAdditionalLinesCommand => new RelayCommand(UpdateAdditionalLines);
- public ICommand ExitCommand => new RelayCommand(() => { Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread().TryEnqueue(Application.Current.Exit); });
+ public ICommand ExitCommand => new RelayCommand(() => { Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread().TryEnqueue(() => { Environment.Exit(0); }); });
public HostsMainPage(MainViewModel viewModel)
{
diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp
index d4f90ba678..214d8c0818 100644
--- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp
+++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.cpp
@@ -111,7 +111,11 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
#endif
_overlayUIStates.push_back(std::move(overlayUI));
}
+
+ trace.UpdateState(true);
Trace::BoundsToolActivated();
+ trace.Flush();
+ trace.UpdateState(false);
}
void Core::StartMeasureTool(const bool horizontal, const bool vertical)
@@ -160,7 +164,10 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
_screenCaptureThreads.emplace_back(std::move(thread));
}
+ trace.UpdateState(true);
Trace::MeasureToolActivated();
+ trace.Flush();
+ trace.UpdateState(false);
}
void MeasureToolCore::implementation::Core::SetToolCompletionEvent(ToolSessionCompleted sessionCompletedTrigger)
diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h
index 79728794a9..da0b3afb17 100644
--- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h
+++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.h
@@ -5,6 +5,7 @@
#include "OverlayUI.h"
#include "Settings.h"
+#include
#include
#include "ScreenCapturing.h"
@@ -50,6 +51,7 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
BoundsToolState _boundsToolState;
CommonState _commonState;
Settings _settings;
+ Shared::Trace::ETWTrace trace{};
};
}
diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
index b05546d9aa..5bdad6767c 100644
--- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
+++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj
@@ -125,6 +125,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/MeasureTool/MeasureToolCore/pch.h b/src/modules/MeasureTool/MeasureToolCore/pch.h
index 67ca0f9d8c..16cc5a1a62 100644
--- a/src/modules/MeasureTool/MeasureToolCore/pch.h
+++ b/src/modules/MeasureTool/MeasureToolCore/pch.h
@@ -30,7 +30,6 @@
#include
#include
#include
-#include
// Undefine GetCurrentTime macro to prevent
// conflict with Storyboard::GetCurrentTime
diff --git a/src/modules/MeasureTool/MeasureToolModuleInterface/pch.h b/src/modules/MeasureTool/MeasureToolModuleInterface/pch.h
index 207418a921..9e02b6c9ce 100644
--- a/src/modules/MeasureTool/MeasureToolModuleInterface/pch.h
+++ b/src/modules/MeasureTool/MeasureToolModuleInterface/pch.h
@@ -9,6 +9,5 @@
#include
#include
-#include
#include
#include
diff --git a/src/modules/MeasureTool/MeasureToolModuleInterface/trace.cpp b/src/modules/MeasureTool/MeasureToolModuleInterface/trace.cpp
index 8c1bb93605..1a56838048 100644
--- a/src/modules/MeasureTool/MeasureToolModuleInterface/trace.cpp
+++ b/src/modules/MeasureTool/MeasureToolModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,19 +10,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::EnableMeasureTool(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MeasureTool_EnableMeasureTool",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -30,7 +22,7 @@ void Trace::EnableMeasureTool(const bool enabled) noexcept
void Trace::BoundsToolActivated() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MeasureTool_BoundsToolActivated",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -39,7 +31,7 @@ void Trace::BoundsToolActivated() noexcept
void Trace::MeasureToolActivated() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MeasureTool_MeasureToolActivated",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MeasureTool/MeasureToolModuleInterface/trace.h b/src/modules/MeasureTool/MeasureToolModuleInterface/trace.h
index e85a14bb38..fb2019c8d5 100644
--- a/src/modules/MeasureTool/MeasureToolModuleInterface/trace.h
+++ b/src/modules/MeasureTool/MeasureToolModuleInterface/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
static void EnableMeasureTool(const bool enabled) noexcept;
static void BoundsToolActivated() noexcept;
diff --git a/src/modules/MouseUtils/FindMyMouse/pch.h b/src/modules/MouseUtils/FindMyMouse/pch.h
index 6dbc256004..26da2455f2 100644
--- a/src/modules/MouseUtils/FindMyMouse/pch.h
+++ b/src/modules/MouseUtils/FindMyMouse/pch.h
@@ -15,6 +15,5 @@
#endif
#include
-#include
#include
#include
diff --git a/src/modules/MouseUtils/FindMyMouse/trace.cpp b/src/modules/MouseUtils/FindMyMouse/trace.cpp
index a5cfe02417..bf79461e9a 100644
--- a/src/modules/MouseUtils/FindMyMouse/trace.cpp
+++ b/src/modules/MouseUtils/FindMyMouse/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has FindMyMouse enabled or disabled
void Trace::EnableFindMyMouse(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FindMyMouse_EnableFindMyMouse",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +24,7 @@ void Trace::EnableFindMyMouse(const bool enabled) noexcept
// Log that the user activated the module by focusing the mouse pointer
void Trace::MousePointerFocused() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FindMyMouse_MousePointerFocused",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MouseUtils/FindMyMouse/trace.h b/src/modules/MouseUtils/FindMyMouse/trace.h
index 623ce60176..59d3183b5b 100644
--- a/src/modules/MouseUtils/FindMyMouse/trace.h
+++ b/src/modules/MouseUtils/FindMyMouse/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log if the user has FindMyMouse enabled or disabled
static void EnableFindMyMouse(const bool enabled) noexcept;
diff --git a/src/modules/MouseUtils/MouseHighlighter/pch.h b/src/modules/MouseUtils/MouseHighlighter/pch.h
index bfb4a4776a..da08f4898a 100644
--- a/src/modules/MouseUtils/MouseHighlighter/pch.h
+++ b/src/modules/MouseUtils/MouseHighlighter/pch.h
@@ -16,7 +16,6 @@
#include
#endif
-#include
#include
#include
#include
diff --git a/src/modules/MouseUtils/MouseHighlighter/trace.cpp b/src/modules/MouseUtils/MouseHighlighter/trace.cpp
index feefa17745..7f8d413b5a 100644
--- a/src/modules/MouseUtils/MouseHighlighter/trace.cpp
+++ b/src/modules/MouseUtils/MouseHighlighter/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has MouseHighlighter enabled or disabled
void Trace::EnableMouseHighlighter(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseHighlighter_EnableMouseHighlighter",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +24,7 @@ void Trace::EnableMouseHighlighter(const bool enabled) noexcept
// Log that the user activated the module by starting a highlighting session
void Trace::StartHighlightingSession() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseHighlighter_StartHighlightingSession",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MouseUtils/MouseHighlighter/trace.h b/src/modules/MouseUtils/MouseHighlighter/trace.h
index 01d660bbc0..12708940e9 100644
--- a/src/modules/MouseUtils/MouseHighlighter/trace.h
+++ b/src/modules/MouseUtils/MouseHighlighter/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log if the user has MouseHighlighter enabled or disabled
static void EnableMouseHighlighter(const bool enabled) noexcept;
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/DrawingHelperTests.cs b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/DrawingHelperTests.cs
similarity index 82%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/DrawingHelperTests.cs
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/DrawingHelperTests.cs
index 1859d085b5..5ba0a0eef8 100644
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/DrawingHelperTests.cs
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/DrawingHelperTests.cs
@@ -2,20 +2,15 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using MouseJumpUI.Common.Helpers;
-using MouseJumpUI.Common.Imaging;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Styles;
-using MouseJumpUI.Helpers;
+using MouseJump.Common.Helpers;
+using MouseJump.Common.Imaging;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Styles;
-namespace MouseJumpUI.UnitTests.Common.Helpers;
+namespace MouseJump.Common.UnitTests.Helpers;
[TestClass]
public static class DrawingHelperTests
@@ -60,8 +55,8 @@ public static class DrawingHelperTests
new(0, 500, 500, 500),
},
activatedLocation: new(x: 50, y: 50),
- desktopImageFilename: "Common/Helpers/_test-4grid-desktop.png",
- expectedImageFilename: "Common/Helpers/_test-4grid-expected.png"),
+ desktopImageFilename: "_test-4grid-desktop.png",
+ expectedImageFilename: "_test-4grid-expected.png"),
};
/* win 11 */
yield return new object[]
@@ -74,8 +69,8 @@ public static class DrawingHelperTests
new(0, 0, 5120, 1440),
},
activatedLocation: new(x: 50, y: 50),
- desktopImageFilename: "Common/Helpers/_test-win11-desktop.png",
- expectedImageFilename: "Common/Helpers/_test-win11-expected.png"),
+ desktopImageFilename: "_test-win11-desktop.png",
+ expectedImageFilename: "_test-win11-expected.png"),
};
}
@@ -104,13 +99,19 @@ public static class DrawingHelperTests
private static Bitmap LoadImageResource(string filename)
{
+ // assume embedded resources are in the same source folder as this
+ // class, and the namespace hierarchy matches the folder structure.
+ // that way we can build resource names from the current namespace
+ var resourcePrefix = typeof(DrawingHelperTests).Namespace;
+ var resourceName = $"{resourcePrefix}.{filename}";
+
var assembly = Assembly.GetExecutingAssembly();
- var assemblyName = new AssemblyName(assembly.FullName ?? throw new InvalidOperationException());
- var resourceName = $"Microsoft.{assemblyName.Name}.{filename.Replace("/", ".")}";
var resourceNames = assembly.GetManifestResourceNames();
if (!resourceNames.Contains(resourceName))
{
- throw new InvalidOperationException($"Embedded resource '{resourceName}' does not exist.");
+ var message = $"Embedded resource '{resourceName}' does not exist. " +
+ "Valid resource names are: \r\n" + string.Join("\r\n", resourceNames);
+ throw new InvalidOperationException(message);
}
var stream = assembly.GetManifestResourceStream(resourceName)
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/LayoutHelperTests.cs b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/LayoutHelperTests.cs
similarity index 98%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/LayoutHelperTests.cs
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/LayoutHelperTests.cs
index 13141b9268..5bdd4af443 100644
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/LayoutHelperTests.cs
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/LayoutHelperTests.cs
@@ -2,17 +2,15 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.Generic;
-using System.Drawing;
using System.Text.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using MouseJumpUI.Common.Helpers;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Layout;
-using MouseJumpUI.Common.Models.Styles;
+using MouseJump.Common.Helpers;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Layout;
+using MouseJump.Common.Models.Styles;
-namespace MouseJumpUI.UnitTests.Common.Helpers;
+namespace MouseJump.Common.UnitTests.Helpers;
[TestClass]
public static class LayoutHelperTests
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/MouseHelperTests.cs b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/MouseHelperTests.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/MouseHelperTests.cs
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/MouseHelperTests.cs
index b7e3b8a99e..52870e8cc1 100644
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/MouseHelperTests.cs
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/MouseHelperTests.cs
@@ -2,13 +2,11 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.Generic;
-
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using MouseJumpUI.Common.Helpers;
-using MouseJumpUI.Common.Models.Drawing;
+using MouseJump.Common.Helpers;
+using MouseJump.Common.Models.Drawing;
-namespace MouseJumpUI.UnitTests.Common.Helpers;
+namespace MouseJump.Common.UnitTests.Helpers;
[TestClass]
public static class MouseHelperTests
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-4grid-desktop.png b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-4grid-desktop.png
similarity index 100%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-4grid-desktop.png
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-4grid-desktop.png
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-4grid-expected.png b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-4grid-expected.png
similarity index 100%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-4grid-expected.png
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-4grid-expected.png
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-win11-desktop.png b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-win11-desktop.png
similarity index 100%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-win11-desktop.png
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-win11-desktop.png
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-win11-expected.png b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-win11-expected.png
similarity index 100%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Helpers/_test-win11-expected.png
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Helpers/_test-win11-expected.png
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/RectangleInfoTests.cs b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/RectangleInfoTests.cs
similarity index 97%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/RectangleInfoTests.cs
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/RectangleInfoTests.cs
index 87d3128e3b..d2d6aba81c 100644
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/RectangleInfoTests.cs
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/RectangleInfoTests.cs
@@ -2,12 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.Generic;
-
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using MouseJumpUI.Common.Models.Drawing;
+using MouseJump.Common.Models.Drawing;
-namespace MouseJumpUI.UnitTests.Common.Models.Drawing;
+namespace MouseJump.Common.UnitTests.Models.Drawing;
[TestClass]
public static class RectangleInfoTests
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/SizeInfoTests.cs b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/SizeInfoTests.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/SizeInfoTests.cs
rename to src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/SizeInfoTests.cs
index 150b15cdc1..e6c33e3d7a 100644
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Common/Models/Drawing/SizeInfoTests.cs
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/Models/Drawing/SizeInfoTests.cs
@@ -2,12 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.Generic;
-
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using MouseJumpUI.Common.Models.Drawing;
+using MouseJump.Common.Models.Drawing;
-namespace MouseJumpUI.UnitTests.Common.Models.Drawing;
+namespace MouseJump.Common.UnitTests.Models.Drawing;
[TestClass]
public static class SizeInfoTests
diff --git a/src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj b/src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj
new file mode 100644
index 0000000000..c97b009bb6
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}
+ PowerToys.MouseJump.Common.UnitTests
+ PowerToys.MouseJump.Common.UnitTests
+ PowerToys MouseJump.Common.UnitTests
+ Library
+ ..\..\..\..\$(Platform)\$(Configuration)\tests\MouseJump.Common.UnitTests\
+ false
+ false
+
+ enable
+ true
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/DrawingHelper.cs b/src/modules/MouseUtils/MouseJump.Common/Helpers/DrawingHelper.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Helpers/DrawingHelper.cs
rename to src/modules/MouseUtils/MouseJump.Common/Helpers/DrawingHelper.cs
index 0f60adae06..278e07039f 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/DrawingHelper.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Helpers/DrawingHelper.cs
@@ -2,22 +2,18 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
using System.Diagnostics;
-using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
-using System.Linq;
-using MouseJumpUI.Common.Imaging;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Layout;
-using MouseJumpUI.Common.Models.Styles;
+using MouseJump.Common.Imaging;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Layout;
+using MouseJump.Common.Models.Styles;
-namespace MouseJumpUI.Common.Helpers;
+namespace MouseJump.Common.Helpers;
-internal static class DrawingHelper
+public static class DrawingHelper
{
public static Bitmap RenderPreview(
PreviewLayout previewLayout,
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/LayoutHelper.cs b/src/modules/MouseUtils/MouseJump.Common/Helpers/LayoutHelper.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Helpers/LayoutHelper.cs
rename to src/modules/MouseUtils/MouseJump.Common/Helpers/LayoutHelper.cs
index f83540d1c0..791d1f7ffb 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/LayoutHelper.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Helpers/LayoutHelper.cs
@@ -2,17 +2,13 @@
// 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 MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Layout;
+using MouseJump.Common.Models.Styles;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Layout;
-using MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Helpers;
-namespace MouseJumpUI.Common.Helpers;
-
-internal static class LayoutHelper
+public static class LayoutHelper
{
public static PreviewLayout GetPreviewLayout(
PreviewStyle previewStyle, List screens, PointInfo activatedLocation)
@@ -111,7 +107,7 @@ internal static class LayoutHelper
/// A object that represents the bounds of the different areas of the box.
/// Thrown when or is null.
/// Thrown when any of the styles in is null.
- internal static BoxBounds GetBoxBoundsFromContentBounds(
+ public static BoxBounds GetBoxBoundsFromContentBounds(
RectangleInfo contentBounds,
BoxStyle boxStyle)
{
@@ -139,7 +135,7 @@ internal static class LayoutHelper
/// A object that represents the bounds of the different areas of the box.
/// Thrown when or is null.
/// Thrown when any of the styles in is null.
- internal static BoxBounds GetBoxBoundsFromOuterBounds(
+ public static BoxBounds GetBoxBoundsFromOuterBounds(
RectangleInfo outerBounds,
BoxStyle boxStyle)
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/MouseHelper.cs b/src/modules/MouseUtils/MouseJump.Common/Helpers/MouseHelper.cs
similarity index 90%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Helpers/MouseHelper.cs
rename to src/modules/MouseUtils/MouseJump.Common/Helpers/MouseHelper.cs
index 1c116bf2c0..9354958878 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/MouseHelper.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Helpers/MouseHelper.cs
@@ -5,15 +5,14 @@
using System.ComponentModel;
using System.Runtime.InteropServices;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.NativeMethods;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.NativeMethods;
+using static MouseJump.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.User32;
-using static MouseJumpUI.Common.NativeMethods.Core;
-using static MouseJumpUI.Common.NativeMethods.User32;
+namespace MouseJump.Common.Helpers;
-namespace MouseJumpUI.Common.Helpers;
-
-internal static class MouseHelper
+public static class MouseHelper
{
///
/// Calculates where to move the cursor to by projecting a point from
@@ -24,7 +23,7 @@ internal static class MouseHelper
/// or even negative if the primary monitor is not the at the top-left of the
/// entire desktop rectangle, so results may contain negative coordinates.
///
- internal static PointInfo GetJumpLocation(PointInfo previewLocation, SizeInfo previewSize, RectangleInfo desktopBounds)
+ public static PointInfo GetJumpLocation(PointInfo previewLocation, SizeInfo previewSize, RectangleInfo desktopBounds)
{
return previewLocation
.Scale(previewSize.ScaleToFitRatio(desktopBounds.Size))
@@ -34,7 +33,7 @@ internal static class MouseHelper
///
/// Get the current position of the cursor.
///
- internal static PointInfo GetCursorPosition()
+ public static PointInfo GetCursorPosition()
{
var lpPoint = new LPPOINT(new POINT(0, 0));
var result = User32.GetCursorPos(lpPoint);
@@ -57,7 +56,7 @@ internal static class MouseHelper
///
/// See https://github.com/mikeclayton/FancyMouse/pull/3
///
- internal static void SetCursorPosition(PointInfo location)
+ public static void SetCursorPosition(PointInfo location)
{
// set the new cursor position *twice* - the cursor sometimes end up in
// the wrong place if we try to cross the dead space between non-aligned
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/ScreenHelper.cs b/src/modules/MouseUtils/MouseJump.Common/Helpers/ScreenHelper.cs
similarity index 87%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Helpers/ScreenHelper.cs
rename to src/modules/MouseUtils/MouseJump.Common/Helpers/ScreenHelper.cs
index 2cdc009867..a863b45bbe 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Helpers/ScreenHelper.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Helpers/ScreenHelper.cs
@@ -2,26 +2,22 @@
// 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.Linq;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.NativeMethods;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.NativeMethods;
+using static MouseJump.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.User32;
-using static MouseJumpUI.Common.NativeMethods.Core;
-using static MouseJumpUI.Common.NativeMethods.User32;
+namespace MouseJump.Common.Helpers;
-namespace MouseJumpUI.Common.Helpers;
-
-internal static class ScreenHelper
+public static class ScreenHelper
{
///
/// Duplicates functionality available in System.Windows.Forms.SystemInformation
/// to reduce the dependency on WinForms
///
- public static RectangleInfo GetVirtualScreen()
+ private static RectangleInfo GetVirtualScreen()
{
return new(
User32.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_XVIRTUALSCREEN),
@@ -30,7 +26,7 @@ internal static class ScreenHelper
User32.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYVIRTUALSCREEN));
}
- internal static IEnumerable GetAllScreens()
+ public static IEnumerable GetAllScreens()
{
// enumerate the monitors attached to the system
var hMonitors = new List();
@@ -80,7 +76,7 @@ internal static class ScreenHelper
}
}
- internal static ScreenInfo GetScreenFromPoint(
+ public static ScreenInfo GetScreenFromPoint(
List screens,
PointInfo pt)
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Helpers/StyleHelper.cs b/src/modules/MouseUtils/MouseJump.Common/Helpers/StyleHelper.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Helpers/StyleHelper.cs
rename to src/modules/MouseUtils/MouseJump.Common/Helpers/StyleHelper.cs
index c6a248f906..2f02ae507d 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Helpers/StyleHelper.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Helpers/StyleHelper.cs
@@ -2,15 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Drawing;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Styles;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Helpers;
-namespace MouseJumpUI.Helpers;
-
-internal static class StyleHelper
+public static class StyleHelper
{
///
/// Default v2 preview style
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/DesktopImageRegionCopyService.cs b/src/modules/MouseUtils/MouseJump.Common/Imaging/DesktopImageRegionCopyService.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Imaging/DesktopImageRegionCopyService.cs
rename to src/modules/MouseUtils/MouseJump.Common/Imaging/DesktopImageRegionCopyService.cs
index 45b8251305..07ba85d09c 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/DesktopImageRegionCopyService.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Imaging/DesktopImageRegionCopyService.cs
@@ -2,22 +2,19 @@
// 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 MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.NativeMethods;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.NativeMethods;
+using static MouseJump.Common.NativeMethods.Core;
-using static MouseJumpUI.Common.NativeMethods.Core;
-
-namespace MouseJumpUI.Common.Imaging;
+namespace MouseJump.Common.Imaging;
///
/// Implements an IImageRegionCopyService that uses the current desktop window as the copy source.
/// This is used during the main application runtime to generate preview images of the desktop.
///
-internal sealed class DesktopImageRegionCopyService : IImageRegionCopyService
+public sealed class DesktopImageRegionCopyService : IImageRegionCopyService
{
///
/// Copies the source region from the current desktop window
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/IImageRegionCopyService.cs b/src/modules/MouseUtils/MouseJump.Common/Imaging/IImageRegionCopyService.cs
similarity index 84%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Imaging/IImageRegionCopyService.cs
rename to src/modules/MouseUtils/MouseJump.Common/Imaging/IImageRegionCopyService.cs
index 0b9e573446..c352510e6b 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/IImageRegionCopyService.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Imaging/IImageRegionCopyService.cs
@@ -2,13 +2,11 @@
// 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.Drawing;
+using MouseJump.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Imaging;
-namespace MouseJumpUI.Common.Imaging;
-
-internal interface IImageRegionCopyService
+public interface IImageRegionCopyService
{
///
/// Copies the source region from the provider's source image (e.g. the interactive desktop,
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/StaticImageRegionCopyService.cs b/src/modules/MouseUtils/MouseJump.Common/Imaging/StaticImageRegionCopyService.cs
similarity index 85%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Imaging/StaticImageRegionCopyService.cs
rename to src/modules/MouseUtils/MouseJump.Common/Imaging/StaticImageRegionCopyService.cs
index 313a5a0b86..6808ff09e6 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Imaging/StaticImageRegionCopyService.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Imaging/StaticImageRegionCopyService.cs
@@ -2,18 +2,15 @@
// 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 MouseJump.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Drawing;
-
-namespace MouseJumpUI.Common.Imaging;
+namespace MouseJump.Common.Imaging;
///
/// Implements an IImageRegionCopyService that uses the specified image as the copy source.
/// This is used for testing the DrawingHelper rather than as part of the main application.
///
-internal sealed class StaticImageRegionCopyService : IImageRegionCopyService
+public sealed class StaticImageRegionCopyService : IImageRegionCopyService
{
public StaticImageRegionCopyService(Image sourceImage)
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/BoxBounds.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/BoxBounds.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/BoxBounds.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Drawing/BoxBounds.cs
index 8b04ab9d28..0c2d81a196 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/BoxBounds.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/BoxBounds.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Models.Drawing;
public sealed class BoxBounds
{
@@ -28,7 +26,7 @@ public sealed class BoxBounds
*/
- internal BoxBounds(
+ public BoxBounds(
RectangleInfo outerBounds,
RectangleInfo marginBounds,
RectangleInfo borderBounds,
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/PointInfo.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/PointInfo.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/PointInfo.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Drawing/PointInfo.cs
index 41ba60eec4..676fdb92c0 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/PointInfo.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/PointInfo.cs
@@ -2,10 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Drawing;
-
-namespace MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Models.Drawing;
///
/// Immutable version of a System.Drawing.Point object with some extra utility methods.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/RectangleInfo.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/RectangleInfo.cs
similarity index 98%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/RectangleInfo.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Drawing/RectangleInfo.cs
index 71db6b5018..e0f8c3b7ef 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/RectangleInfo.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/RectangleInfo.cs
@@ -2,15 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Drawing;
using System.Text.Json.Serialization;
-using MouseJumpUI.Common.Models.Styles;
+using MouseJump.Common.Models.Styles;
+using BorderStyle = MouseJump.Common.Models.Styles.BorderStyle;
-using BorderStyle = MouseJumpUI.Common.Models.Styles.BorderStyle;
-
-namespace MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Models.Drawing;
///
/// Immutable version of a System.Drawing.Rectangle object with some extra utility methods.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/ScreenInfo.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/ScreenInfo.cs
similarity index 76%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/ScreenInfo.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Drawing/ScreenInfo.cs
index a671be7cec..b1e9c9327a 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/ScreenInfo.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/ScreenInfo.cs
@@ -2,19 +2,15 @@
// 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 static MouseJumpUI.Common.NativeMethods.Core;
-
-namespace MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Models.Drawing;
///
/// Immutable version of a System.Windows.Forms.Screen object so we don't need to
/// take a dependency on WinForms just for screen info.
///
-internal sealed class ScreenInfo
+public sealed class ScreenInfo
{
- internal ScreenInfo(HMONITOR handle, bool primary, RectangleInfo displayArea, RectangleInfo workingArea)
+ public ScreenInfo(int handle, bool primary, RectangleInfo displayArea, RectangleInfo workingArea)
{
this.Handle = handle;
this.Primary = primary;
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/SizeInfo.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/SizeInfo.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/SizeInfo.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Drawing/SizeInfo.cs
index 3216e4d367..ffb0b4de10 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Drawing/SizeInfo.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Drawing/SizeInfo.cs
@@ -2,14 +2,10 @@
// 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 MouseJump.Common.Models.Styles;
+using BorderStyle = MouseJump.Common.Models.Styles.BorderStyle;
-using MouseJumpUI.Common.Models.Styles;
-
-using BorderStyle = MouseJumpUI.Common.Models.Styles.BorderStyle;
-
-namespace MouseJumpUI.Common.Models.Drawing;
+namespace MouseJump.Common.Models.Drawing;
///
/// Immutable version of a System.Drawing.Size object with some extra utility methods.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Layout/PreviewLayout.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Layout/PreviewLayout.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Layout/PreviewLayout.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Layout/PreviewLayout.cs
index e09a45e79f..342389d45d 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Layout/PreviewLayout.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Layout/PreviewLayout.cs
@@ -2,15 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Linq;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Styles;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Styles;
-namespace MouseJumpUI.Common.Models.Layout;
+namespace MouseJump.Common.Models.Layout;
public sealed class PreviewLayout
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BackgroundStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BackgroundStyle.cs
similarity index 92%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BackgroundStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/BackgroundStyle.cs
index 332a55fcbe..1d6609a676 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BackgroundStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BackgroundStyle.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Drawing;
-
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
///
/// Represents the background fill style for a drawing object.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BorderStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BorderStyle.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BorderStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/BorderStyle.cs
index 3c5b870e60..a8773b535d 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BorderStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BorderStyle.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Drawing;
-
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
///
/// Represents the border style for a drawing object.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BoxStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BoxStyle.cs
similarity index 97%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BoxStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/BoxStyle.cs
index dac908b05c..55e27c3b9f 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/BoxStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/BoxStyle.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
///
/// Represents the styles to apply to a simple box-layout based drawing object.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/MarginStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/MarginStyle.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/MarginStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/MarginStyle.cs
index 6dce63f57b..b0a369dfe7 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/MarginStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/MarginStyle.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
///
/// Represents the margin style for a drawing object.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PaddingStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/PaddingStyle.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PaddingStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/PaddingStyle.cs
index 6ac7bc6b11..d4b0c82b40 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PaddingStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/PaddingStyle.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
///
/// Represents the margin style for a drawing object.
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PreviewStyle.cs b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/PreviewStyle.cs
similarity index 89%
rename from src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PreviewStyle.cs
rename to src/modules/MouseUtils/MouseJump.Common/Models/Styles/PreviewStyle.cs
index 8b2405d59a..2ca2b1bc28 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/Models/Styles/PreviewStyle.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Models/Styles/PreviewStyle.cs
@@ -2,11 +2,9 @@
// 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 MouseJump.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Drawing;
-
-namespace MouseJumpUI.Common.Models.Styles;
+namespace MouseJump.Common.Models.Styles;
public sealed class PreviewStyle
{
diff --git a/src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj b/src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj
new file mode 100644
index 0000000000..4b56443fa7
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ {923DF87C-CA99-4D1C-B1D2-959174E95BFA}
+ PowerToys.MouseJump.Common
+ PowerToys.MouseJump.Common
+ PowerToys MouseJump.Common
+ Library
+ ..\..\..\..\$(Platform)\$(Configuration)
+ false
+ false
+
+ PerMonitorV2
+ true
+ enable
+ true
+ enable
+
+
+
+
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/BOOL.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/BOOL.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/BOOL.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/BOOL.cs
index ec8849d952..293ae0a226 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/BOOL.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/BOOL.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/CRECT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/CRECT.cs
similarity index 97%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/CRECT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/CRECT.cs
index 3b02b3bf5e..03e3d8efd1 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/CRECT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/CRECT.cs
@@ -5,7 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/DWORD.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/DWORD.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/DWORD.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/DWORD.cs
index 900b5bfb77..5a7ae72697 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/DWORD.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/DWORD.cs
@@ -4,7 +4,7 @@
using System.Runtime.InteropServices;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HANDLE.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HANDLE.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HANDLE.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HANDLE.cs
index c89132e0be..d32f6f8e3c 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HANDLE.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HANDLE.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HDC.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HDC.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HDC.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HDC.cs
index 0996030b01..038ae8df2b 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HDC.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HDC.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HMONITOR.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HMONITOR.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HMONITOR.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HMONITOR.cs
index 5baa77bfc5..9344208770 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HMONITOR.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HMONITOR.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HWND.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HWND.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HWND.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HWND.cs
index e421a1ca91..715f922b66 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/HWND.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/HWND.cs
@@ -2,10 +2,9 @@
// 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.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LONG.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LONG.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LONG.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LONG.cs
index 7fe4b6cb99..3ac457eb44 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LONG.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LONG.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPARAM.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPARAM.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPARAM.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPARAM.cs
index f214e53a6f..f93e089b12 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPARAM.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPARAM.cs
@@ -1,9 +1,8 @@
// 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;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPCRECT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPCRECT.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPCRECT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPCRECT.cs
index c23dbbfb85..5cc6d9f3c7 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPCRECT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPCRECT.cs
@@ -2,10 +2,9 @@
// 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 MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPPOINT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPPOINT.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPPOINT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPPOINT.cs
index c68d8b336b..725cc154d1 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPPOINT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPPOINT.cs
@@ -2,10 +2,9 @@
// 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 MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPRECT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPRECT.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPRECT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPRECT.cs
index 66f22da181..31ba69fd4c 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/LPRECT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/LPRECT.cs
@@ -1,10 +1,10 @@
// 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 MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/POINT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/POINT.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/POINT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/POINT.cs
index 6077174ce6..a843059b99 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/POINT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/POINT.cs
@@ -5,7 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/RECT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/RECT.cs
similarity index 97%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/RECT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/RECT.cs
index 084616cc77..04df9a98c8 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/RECT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/RECT.cs
@@ -5,7 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/UINT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/UINT.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/UINT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/UINT.cs
index d2ce9a2e51..f178f8f866 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/UINT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/UINT.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/ULONG_PTR.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/ULONG_PTR.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/ULONG_PTR.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/ULONG_PTR.cs
index ed26092cb1..b8a8764c3a 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/ULONG_PTR.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/ULONG_PTR.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/WORD.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/WORD.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/WORD.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/WORD.cs
index 987b532f29..8ef05dd17a 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Core/WORD.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Core/WORD.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Core
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs
similarity index 96%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs
index 1cb5261967..4f4a9673c4 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.ROP_CODE.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Gdi32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs
index f1417941d3..0b25a3d565 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.STRETCH_BLT_MODE.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Gdi32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs
similarity index 90%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs
index e2aa26b8dd..95c71137a5 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.SetStretchBltMode.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Gdi32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs
similarity index 92%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs
index 4c74de99a4..f6f9243815 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Gdi32/Graphics/Gdi/Gdi32.StretchBlt.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class Gdi32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Libraries.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Libraries.cs
similarity index 87%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Libraries.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/Libraries.cs
index e648f9b01b..970183cab0 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/Libraries.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/Libraries.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static class Libraries
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs
index 2572e40881..7ebbea2dfa 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.EnumDisplayMonitors.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs
similarity index 89%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs
index f6680a3a27..cd328f76cc 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetMonitorInfoW.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs
index ce5cf1afb5..229dedcdf1 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.GetWindowDC.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs
index 3896962d71..d70342fa0b 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.LPMONITORINFO.cs
@@ -2,10 +2,9 @@
// 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 MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs
similarity index 87%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs
index 169bf3e567..017f8a2d72 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORENUMPROC .cs
@@ -2,9 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs
index 97af859180..06c5a07b7e 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITORINFO.cs
@@ -5,9 +5,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs
index c566193874..61f15c2944 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_FROM_FLAGS.cs
@@ -4,7 +4,7 @@
using System.Diagnostics.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
[SuppressMessage("SA1310", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Names match Win32 api")]
internal static partial class User32
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs
index 8bfa14eb55..c7bbe4033b 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MONITOR_INFO_FLAGS.cs
@@ -4,7 +4,7 @@
using System.Diagnostics.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
[SuppressMessage("SA1310", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Names match Win32 api")]
internal static partial class User32
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs
similarity index 91%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs
index a511631f1e..04eb36a312 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.MonitorFromPoint .cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs
similarity index 91%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs
index 20e1ded98f..6fa39e023d 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/Graphics/Gdi/User32.ReleaseDC.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs
similarity index 92%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs
index 2959b393e3..84b43227f7 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.HARDWAREINPUT.cs
@@ -5,9 +5,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs
index 9a4b1605bd..543e7d8e18 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT.cs
@@ -5,9 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
-
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs
similarity index 94%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs
index b065fdfc43..8fd5a8ad20 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.INPUT_TYPE.cs
@@ -4,7 +4,7 @@
using System.Diagnostics.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
[SuppressMessage("SA1310", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Names match Win32 api")]
internal static partial class User32
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs
index c421841e91..052836d5ef 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.KEYBDINPUT.cs
@@ -5,9 +5,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs
index e803fe3d85..5730ff9dc5 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.LPINPUT.cs
@@ -2,11 +2,9 @@
// 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;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs
similarity index 93%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs
index edc3916ba5..be243b778f 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSEINPUT.cs
@@ -5,9 +5,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs
index 6bfe6d3bbe..08b0780327 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.MOUSE_EVENT_FLAGS.cs
@@ -2,10 +2,9 @@
// 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.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
[SuppressMessage("SA1310", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Names match Win32 api")]
internal static partial class User32
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs
similarity index 91%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs
index b0399d8848..74eb5ac9fb 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/Input/KeyboardAndMouse/User32.SendInput.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs
similarity index 89%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs
index 80af7f7461..1d84e17e2a 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetCursorPos.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs
similarity index 89%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs
index bd2e870b87..8984e9639c 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetDesktopWindow.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs
similarity index 95%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs
index 0865d5af3d..dafa5daadd 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.GetSystemMetrics.cs
@@ -4,7 +4,7 @@
using System.Runtime.InteropServices;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs
similarity index 98%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs
index 5891c53551..8a714ad052 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs
@@ -4,7 +4,7 @@
using System.Diagnostics.CodeAnalysis;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
[SuppressMessage("SA1310", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Names match Win32 api")]
internal static partial class User32
diff --git a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs
similarity index 91%
rename from src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs
rename to src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs
index 6420cd8f5b..b3bb04fef9 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SetCursorPos.cs
@@ -4,9 +4,9 @@
using System.Runtime.InteropServices;
-using static MouseJumpUI.Common.NativeMethods.Core;
+using static MouseJump.Common.NativeMethods.Core;
-namespace MouseJumpUI.Common.NativeMethods;
+namespace MouseJump.Common.NativeMethods;
internal static partial class User32
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/Properties/AssemblyInfo.cs b/src/modules/MouseUtils/MouseJump.Common/Properties/AssemblyInfo.cs
similarity index 78%
rename from src/modules/MouseUtils/MouseJumpUI/Properties/AssemblyInfo.cs
rename to src/modules/MouseUtils/MouseJump.Common/Properties/AssemblyInfo.cs
index b44c65eead..e69edb9c61 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Properties/AssemblyInfo.cs
+++ b/src/modules/MouseUtils/MouseJump.Common/Properties/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using System.Runtime.CompilerServices;
-[assembly: InternalsVisibleTo("MouseJumpUI.UnitTests")]
+[assembly: InternalsVisibleTo("MouseJump.Common.UnitTests")]
diff --git a/src/modules/MouseUtils/MouseJump/dllmain.cpp b/src/modules/MouseUtils/MouseJump/dllmain.cpp
index d687caa063..85894cea15 100644
--- a/src/modules/MouseUtils/MouseJump/dllmain.cpp
+++ b/src/modules/MouseUtils/MouseJump/dllmain.cpp
@@ -62,9 +62,12 @@ private:
Hotkey m_hotkey;
- // Handle to event used to invoke PowerOCR
+ // Handle to event used to invoke MouseJump
HANDLE m_hInvokeEvent;
+ // Handle to event used to terminate MouseJump
+ HANDLE m_hTerminateEvent;
+
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -154,6 +157,7 @@ public:
{
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseJumpLoggerName);
m_hInvokeEvent = CreateDefaultEvent(CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT);
+ m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_MOUSE_JUMP_SHARED_EVENT);
init_settings();
};
@@ -245,6 +249,8 @@ public:
if (m_enabled)
{
ResetEvent(m_hInvokeEvent);
+ SetEvent(m_hTerminateEvent);
+ WaitForSingleObject(m_hProcess, 1500);
TerminateProcess(m_hProcess, 1);
}
diff --git a/src/modules/MouseUtils/MouseJump/pch.h b/src/modules/MouseUtils/MouseJump/pch.h
index 74abb62da1..575f5e9355 100644
--- a/src/modules/MouseUtils/MouseJump/pch.h
+++ b/src/modules/MouseUtils/MouseJump/pch.h
@@ -5,6 +5,5 @@
#include
//#include
-#include
#include
#include
diff --git a/src/modules/MouseUtils/MouseJump/trace.cpp b/src/modules/MouseUtils/MouseJump/trace.cpp
index 9f5380284d..dd2399eb68 100644
--- a/src/modules/MouseUtils/MouseJump/trace.cpp
+++ b/src/modules/MouseUtils/MouseJump/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,19 +10,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::EnableJumpTool(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseJump_EnableJumpTool",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -30,7 +22,7 @@ void Trace::EnableJumpTool(const bool enabled) noexcept
void Trace::InvokeJumpTool() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseJump_InvokeJumpTool",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MouseUtils/MouseJump/trace.h b/src/modules/MouseUtils/MouseJump/trace.h
index aaaa336291..c70e2c746c 100644
--- a/src/modules/MouseUtils/MouseJump/trace.h
+++ b/src/modules/MouseUtils/MouseJump/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
static void EnableJumpTool(const bool enabled) noexcept;
static void InvokeJumpTool() noexcept;
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/MouseJumpUI.UnitTests.csproj b/src/modules/MouseUtils/MouseJumpUI.UnitTests/MouseJumpUI.UnitTests.csproj
deleted file mode 100644
index 67720c8bcd..0000000000
--- a/src/modules/MouseUtils/MouseJumpUI.UnitTests/MouseJumpUI.UnitTests.csproj
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
- {D9C5DE64-6849-4278-91AD-9660AECF2876}
- Microsoft.MouseJumpUI.UnitTests
- false
- enable
- Library
-
-
-
- ..\..\..\..\$(Platform)\$(Configuration)\tests\MouseJumpUI.UnitTests\
-
-
-
-
-
-
- runtime
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs b/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs
index cade054f69..cfd10fbd78 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs
+++ b/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs
@@ -13,7 +13,7 @@ using Microsoft.PowerToys.Settings.UI.Library.Utilities;
namespace MouseJumpUI.Helpers;
-internal class SettingsHelper
+internal sealed class SettingsHelper
{
public SettingsHelper()
{
diff --git a/src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs b/src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs
index 6300590e73..efc4310665 100644
--- a/src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs
+++ b/src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs
@@ -6,7 +6,7 @@ using System.Windows.Forms;
namespace MouseJumpUI;
-partial class MainForm
+internal sealed partial class MainForm
{
///
diff --git a/src/modules/MouseUtils/MouseJumpUI/MainForm.cs b/src/modules/MouseUtils/MouseJumpUI/MainForm.cs
index 1b8b311d89..1c6e94a1a9 100644
--- a/src/modules/MouseUtils/MouseJumpUI/MainForm.cs
+++ b/src/modules/MouseUtils/MouseJumpUI/MainForm.cs
@@ -9,15 +9,15 @@ using System.Linq;
using System.Windows.Forms;
using ManagedCommon;
-using MouseJumpUI.Common.Helpers;
-using MouseJumpUI.Common.Imaging;
-using MouseJumpUI.Common.Models.Drawing;
-using MouseJumpUI.Common.Models.Layout;
+using MouseJump.Common.Helpers;
+using MouseJump.Common.Imaging;
+using MouseJump.Common.Models.Drawing;
+using MouseJump.Common.Models.Layout;
using MouseJumpUI.Helpers;
namespace MouseJumpUI;
-internal partial class MainForm : Form
+internal sealed partial class MainForm : Form
{
public MainForm(SettingsHelper settingsHelper)
{
@@ -166,6 +166,7 @@ internal partial class MainForm : Form
// move mouse pointer
Logger.LogInfo($"clicked location = {clickedLocation}");
+ Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new Telemetry.MouseJumpTeleportCursorEvent());
MouseHelper.SetCursorPosition(clickedLocation);
}
@@ -202,6 +203,8 @@ internal partial class MainForm : Form
stopwatch.Stop();
+ Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new Telemetry.MouseJumpShowEvent());
+
// we have to activate the form to make sure the deactivate event fires
this.Activate();
}
diff --git a/src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj b/src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj
index 1333ead0c5..4ffd69bee6 100644
--- a/src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj
+++ b/src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj
@@ -4,26 +4,24 @@
+
+ PowerToys.MouseJumpUI
PowerToys.MouseJumpUI
PowerToys MouseJumpUI
+ WinExe
..\..\..\..\$(Platform)\$(Configuration)
false
false
- true
- true
- MouseJumpUI.Program
+
+ PerMonitorV2
true
enable
- PerMonitorV2
- {D962A009-834F-4EEC-AABB-430DF8F98E39}
- WinExe
- MouseJumpUI
- PowerToys.MouseJumpUI
- {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- true
+ true
+ disable
+
-
+
PowerToys.GPOWrapper
$(OutDir)
@@ -36,5 +34,7 @@
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJumpUI/Program.cs b/src/modules/MouseUtils/MouseJumpUI/Program.cs
index 8bd9b183e1..cb9916c33d 100644
--- a/src/modules/MouseUtils/MouseJumpUI/Program.cs
+++ b/src/modules/MouseUtils/MouseJumpUI/Program.cs
@@ -13,6 +13,7 @@ using System.Windows.Threading;
using Common.UI;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Telemetry;
using MouseJumpUI.Helpers;
using PowerToys.Interop;
@@ -20,6 +21,8 @@ namespace MouseJumpUI;
internal static class Program
{
+ private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
+
///
/// The main entry point for the application.
///
@@ -27,6 +30,7 @@ internal static class Program
private static void Main(string[] args)
{
Logger.InitializeLogger("\\MouseJump\\Logs");
+ ETWTrace etwTrace = new ETWTrace();
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
@@ -62,13 +66,10 @@ internal static class Program
Logger.LogInfo($"Mouse Jump started from the PowerToys Runner. Runner pid={runnerPid}");
- var cancellationTokenSource = new CancellationTokenSource();
-
RunnerHelper.WaitForPowerToysRunner(runnerPid, () =>
{
- Logger.LogInfo("PowerToys Runner exited. Exiting Mouse Jump");
- cancellationTokenSource.Cancel();
- Application.Exit();
+ Logger.LogInfo("PowerToys Runner exited.");
+ TerminateApp();
});
var settingsHelper = new SettingsHelper();
@@ -80,7 +81,21 @@ internal static class Program
Dispatcher.CurrentDispatcher,
cancellationTokenSource.Token);
+ NativeEventWaiter.WaitForEventLoop(
+ Constants.TerminateMouseJumpSharedEvent(),
+ TerminateApp,
+ Dispatcher.CurrentDispatcher,
+ cancellationTokenSource.Token);
+
Application.Run();
+ etwTrace?.Dispose();
+ }
+
+ private static void TerminateApp()
+ {
+ Logger.LogInfo("Exiting Mouse Jump.");
+ cancellationTokenSource.Cancel();
+ Application.Exit();
}
private static MouseJumpSettings ReadSettings()
diff --git a/src/modules/MouseUtils/MousePointerCrosshairs/pch.h b/src/modules/MouseUtils/MousePointerCrosshairs/pch.h
index 5fc459cbc9..1240987498 100644
--- a/src/modules/MouseUtils/MousePointerCrosshairs/pch.h
+++ b/src/modules/MouseUtils/MousePointerCrosshairs/pch.h
@@ -9,7 +9,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/src/modules/MouseUtils/MousePointerCrosshairs/trace.cpp b/src/modules/MouseUtils/MousePointerCrosshairs/trace.cpp
index afc9844bc5..00924f030d 100644
--- a/src/modules/MouseUtils/MousePointerCrosshairs/trace.cpp
+++ b/src/modules/MouseUtils/MousePointerCrosshairs/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has MousePointerCrosshairs enabled or disabled
void Trace::EnableMousePointerCrosshairs(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MousePointerCrosshairs_EnableMousePointerCrosshairs",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +24,7 @@ void Trace::EnableMousePointerCrosshairs(const bool enabled) noexcept
// Log that the user activated the module by having the crosshairs be drawn
void Trace::StartDrawingCrosshairs() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MousePointerCrosshairs_StartDrawingCrosshairs",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MouseUtils/MousePointerCrosshairs/trace.h b/src/modules/MouseUtils/MousePointerCrosshairs/trace.h
index d7373e5347..b60fc33336 100644
--- a/src/modules/MouseUtils/MousePointerCrosshairs/trace.h
+++ b/src/modules/MouseUtils/MousePointerCrosshairs/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log if the user has MousePointerCrosshairs enabled or disabled
static void EnableMousePointerCrosshairs(const bool enabled) noexcept;
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
index e476ec3554..68f700c3d4 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
@@ -28,6 +28,7 @@ using Microsoft.PowerToys.Telemetry;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Exceptions;
using SystemClipboard = System.Windows.Forms.Clipboard;
@@ -83,8 +84,8 @@ namespace MouseWithoutBorders
internal static bool CheckClipboardEx(ByteArrayOrString data, bool isFilePath)
{
- LogDebug($"{nameof(CheckClipboardEx)}: ShareClipboard = {Setting.Values.ShareClipboard}, TransferFile = {Setting.Values.TransferFile}, data = {data}.");
- LogDebug($"{nameof(CheckClipboardEx)}: {nameof(Setting.Values.OneWayClipboardMode)} = {Setting.Values.OneWayClipboardMode}.");
+ Logger.LogDebug($"{nameof(CheckClipboardEx)}: ShareClipboard = {Setting.Values.ShareClipboard}, TransferFile = {Setting.Values.TransferFile}, data = {data}.");
+ Logger.LogDebug($"{nameof(CheckClipboardEx)}: {nameof(Setting.Values.OneWayClipboardMode)} = {Setting.Values.OneWayClipboardMode}.");
if (!Setting.Values.ShareClipboard)
{
@@ -98,7 +99,7 @@ namespace MouseWithoutBorders
if (GetTick() - LastClipboardEventTime < 1000)
{
- LogDebug("GetTick() - lastClipboardEventTime < 1000");
+ Logger.LogDebug("GetTick() - lastClipboardEventTime < 1000");
LastClipboardEventTime = GetTick();
return false;
}
@@ -130,7 +131,7 @@ namespace MouseWithoutBorders
{
if (lastClipboardObject is string lastStringData && lastStringData.Equals(stringData, StringComparison.OrdinalIgnoreCase))
{
- LogDebug("CheckClipboardEx: Same string data.");
+ Logger.LogDebug("CheckClipboardEx: Same string data.");
return false;
}
}
@@ -139,11 +140,11 @@ namespace MouseWithoutBorders
if (isFilePath)
{
- Common.LogDebug("Clipboard contains FileDropList");
+ Logger.LogDebug("Clipboard contains FileDropList");
if (!Setting.Values.TransferFile)
{
- Common.LogDebug("TransferFile option is unchecked.");
+ Logger.LogDebug("TransferFile option is unchecked.");
return false;
}
@@ -155,7 +156,7 @@ namespace MouseWithoutBorders
{
if (File.Exists(filePath) && new FileInfo(filePath).Length <= MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT)
{
- LogDebug("Clipboard contains: " + filePath);
+ Logger.LogDebug("Clipboard contains: " + filePath);
LastDragDropFile = filePath;
SendClipboardBeat();
SetToggleIcon(new int[TOGGLE_ICONS_SIZE] { ICON_BIG_CLIPBOARD, -1, ICON_BIG_CLIPBOARD, -1 });
@@ -164,7 +165,7 @@ namespace MouseWithoutBorders
{
if (Directory.Exists(filePath))
{
- LogDebug("Clipboard contains a directory: " + filePath);
+ Logger.LogDebug("Clipboard contains a directory: " + filePath);
LastDragDropFile = filePath;
SendClipboardBeat();
}
@@ -172,7 +173,7 @@ namespace MouseWithoutBorders
{
LastDragDropFile = filePath + " - File too big (greater than 100MB), please drag and drop the file instead!";
SendClipboardBeat();
- Log("Clipboard: File too big: " + filePath);
+ Logger.Log("Clipboard: File too big: " + filePath);
}
SetToggleIcon(new int[TOGGLE_ICONS_SIZE] { ICON_ERROR, -1, ICON_ERROR, -1 });
@@ -180,7 +181,7 @@ namespace MouseWithoutBorders
}
else
{
- Log("CheckClipboardEx: File not found: " + filePath);
+ Logger.Log("CheckClipboardEx: File not found: " + filePath);
}
});
}
@@ -194,7 +195,7 @@ namespace MouseWithoutBorders
s.Write(texts, 0, texts.Length);
}
- Common.LogDebug("Plain/Zip = " + texts.Length.ToString(CultureInfo.CurrentCulture) + "/" +
+ Logger.LogDebug("Plain/Zip = " + texts.Length.ToString(CultureInfo.CurrentCulture) + "/" +
ms.Length.ToString(CultureInfo.CurrentCulture));
LastClipboardData = ms.GetBuffer();
@@ -206,20 +207,20 @@ namespace MouseWithoutBorders
{
if (lastClipboardObject is byte[] lastByteData && Enumerable.SequenceEqual(lastByteData, byteData))
{
- LogDebug("CheckClipboardEx: Same byte[] data.");
+ Logger.LogDebug("CheckClipboardEx: Same byte[] data.");
return false;
}
}
HasSwitchedMachineSinceLastCopy = false;
- Common.LogDebug("Clipboard contains image");
+ Logger.LogDebug("Clipboard contains image");
IsClipboardDataImage = true;
LastClipboardData = byteData;
}
else
{
- LogDebug("*** Clipboard contains something else!");
+ Logger.LogDebug("*** Clipboard contains something else!");
return false;
}
@@ -243,7 +244,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
return false;
@@ -334,7 +335,7 @@ namespace MouseWithoutBorders
ProcessPackage(data, tcp);
if (++unexpectedCount > 100)
{
- Log("ReceiveClipboardDataUsingTCP: unexpectedCount > 100!");
+ Logger.Log("ReceiveClipboardDataUsingTCP: unexpectedCount > 100!");
done = true;
}
@@ -363,7 +364,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log("ReceiveClipboardDataUsingTCP: " + e.Message);
+ Logger.Log("ReceiveClipboardDataUsingTCP: " + e.Message);
}
}
@@ -396,7 +397,7 @@ namespace MouseWithoutBorders
{
if (Sk == null)
{
- Log("ConnectAndGetData: Sk == null!");
+ Logger.Log("ConnectAndGetData: Sk == null!");
return;
}
@@ -404,7 +405,7 @@ namespace MouseWithoutBorders
TcpClient clipboardTcpClient = null;
string postAct = (string)postAction;
- LogDebug("ConnectAndGetData.postAction: " + postAct);
+ Logger.LogDebug("ConnectAndGetData.postAction: " + postAct);
ClipboardPostAction clipboardPostAct = postAct.Contains("mspaint,") ? ClipboardPostAction.Mspaint
: postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase) ? ClipboardPostAction.Desktop
@@ -418,7 +419,7 @@ namespace MouseWithoutBorders
if (!IsConnectedByAClientSocketTo(remoteMachine))
{
- Log($"No potential inbound connection from {MachineName} to {remoteMachine}, ask for a push back instead.");
+ Logger.Log($"No potential inbound connection from {MachineName} to {remoteMachine}, ask for a push back instead.");
ID machineId = MachinePool.ResolveID(remoteMachine);
if (machineId != ID.NONE)
@@ -436,7 +437,7 @@ namespace MouseWithoutBorders
}
else
{
- Log($"Unable to resolve {remoteMachine} to its long IP.");
+ Logger.Log($"Unable to resolve {remoteMachine} to its long IP.");
}
return;
@@ -448,7 +449,7 @@ namespace MouseWithoutBorders
}
catch (ThreadAbortException)
{
- Common.Log("The current thread is being aborted (1).");
+ Logger.Log("The current thread is being aborted (1).");
if (clipboardTcpClient != null && clipboardTcpClient.Connected)
{
clipboardTcpClient.Client.Close();
@@ -458,7 +459,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE]
{
Common.ICON_BIG_CLIPBOARD,
@@ -513,7 +514,7 @@ namespace MouseWithoutBorders
if ((rv = deStream.ReadEx(header, 0, header.Length)) < header.Length)
{
- Common.Log("Reading header failed: " + rv.ToString(CultureInfo.CurrentCulture));
+ Logger.Log("Reading header failed: " + rv.ToString(CultureInfo.CurrentCulture));
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE]
{
Common.ICON_BIG_CLIPBOARD,
@@ -523,12 +524,12 @@ namespace MouseWithoutBorders
}
fileName = Common.GetStringU(header).Replace("\0", string.Empty);
- Common.LogDebug("Header: " + fileName);
+ Logger.LogDebug("Header: " + fileName);
string[] headers = fileName.Split(Star);
if (headers.Length < 2 || !long.TryParse(headers[0], out long dataSize))
{
- Common.Log(string.Format(
+ Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"Reading header failed: {0}:{1}",
headers.Length,
@@ -543,7 +544,7 @@ namespace MouseWithoutBorders
fileName = headers[1];
- Common.LogDebug(string.Format(
+ Logger.LogDebug(string.Format(
CultureInfo.CurrentCulture,
"Receiving {0}:{1} from {2}...",
Path.GetFileName(fileName),
@@ -593,7 +594,7 @@ namespace MouseWithoutBorders
m = new FileStream(tempFile, FileMode.Create);
}
- Common.Log("==> " + tempFile);
+ Logger.Log("==> " + tempFile);
}
ShowToolTip(
@@ -643,7 +644,7 @@ namespace MouseWithoutBorders
if (m != null && fileName != null)
{
m.Flush();
- Common.LogDebug(m.Length.ToString(CultureInfo.CurrentCulture) + " bytes received.");
+ Logger.LogDebug(m.Length.ToString(CultureInfo.CurrentCulture) + " bytes received.");
Common.LastClipboardEventTime = Common.GetTick();
string toolTipText = null;
string sizeText = m.Length >= 1024
@@ -738,7 +739,7 @@ namespace MouseWithoutBorders
}
catch (ThreadAbortException)
{
- Common.Log("The current thread is being aborted (3).");
+ Logger.Log("The current thread is being aborted (3).");
s.Close();
if (m != null)
@@ -754,11 +755,11 @@ namespace MouseWithoutBorders
if (e is IOException)
{
string log = $"{nameof(ReceiveAndProcessClipboardData)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
else
{
- Common.Log(e);
+ Logger.Log(e);
}
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE]
@@ -805,15 +806,15 @@ namespace MouseWithoutBorders
NetworkStream ns = new(s);
enStream = Common.GetEncryptedStream(ns);
Common.SendOrReceiveARandomDataBlockPerInitialIV(enStream);
- LogDebug($"{nameof(ShakeHand)}: Writing header package.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Writing header package.");
enStream.Write(package.Bytes, 0, PACKAGE_SIZE_EX);
- LogDebug($"{nameof(ShakeHand)}: Sent: clientPush={clientPushData}, postAction={postAction}.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Sent: clientPush={clientPushData}, postAction={postAction}.");
deStream = Common.GetDecryptedStream(ns);
Common.SendOrReceiveARandomDataBlockPerInitialIV(deStream, false);
- LogDebug($"{nameof(ShakeHand)}: Reading header package.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Reading header package.");
int bytesReceived = deStream.ReadEx(buf, 0, Common.PACKAGE_SIZE_EX);
package.Bytes = buf;
@@ -826,41 +827,41 @@ namespace MouseWithoutBorders
{
name = remoteName = package.MachineName;
- Common.LogDebug($"{nameof(ShakeHand)}: Connection from {name}:{package.Src}");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Connection from {name}:{package.Src}");
if (Common.MachinePool.ResolveID(name) == package.Src && Common.IsConnectedTo(package.Src))
{
clientPushData = package.Type == PackageType.ClipboardPush;
postAction = package.PostAction;
handShaken = true;
- LogDebug($"{nameof(ShakeHand)}: Received: clientPush={clientPushData}, postAction={postAction}.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Received: clientPush={clientPushData}, postAction={postAction}.");
}
else
{
- Common.LogDebug($"{nameof(ShakeHand)}: No active connection to the machine: {name}.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: No active connection to the machine: {name}.");
}
}
else
{
- Common.LogDebug($"{nameof(ShakeHand)}: Unexpected package type: {package.Type}.");
+ Logger.LogDebug($"{nameof(ShakeHand)}: Unexpected package type: {package.Type}.");
}
}
else
{
- Common.LogDebug($"{nameof(ShakeHand)}: BytesTransferred != PACKAGE_SIZE_EX: {bytesReceived}");
+ Logger.LogDebug($"{nameof(ShakeHand)}: BytesTransferred != PACKAGE_SIZE_EX: {bytesReceived}");
}
if (!handShaken)
{
string msg = $"Clipboard connection rejected: {name}:{remoteName}/{package.Src}\r\n\r\nMake sure you run the same version in all machines.";
- Common.Log(msg);
+ Logger.Log(msg);
Common.ShowToolTip(msg, 3000, ToolTipIcon.Warning);
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE] { Common.ICON_BIG_CLIPBOARD, -1, -1, -1 });
}
}
catch (ThreadAbortException)
{
- Common.Log($"{nameof(ShakeHand)}: The current thread is being aborted.");
+ Logger.Log($"{nameof(ShakeHand)}: The current thread is being aborted.");
s.Close();
}
catch (Exception e)
@@ -868,11 +869,11 @@ namespace MouseWithoutBorders
if (e is IOException)
{
string log = $"{nameof(ShakeHand)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
else
{
- Common.Log(e);
+ Logger.Log(e);
}
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE]
@@ -906,7 +907,7 @@ namespace MouseWithoutBorders
Common.DoSomethingInUIThread(() => Common.MainForm.ChangeIcon(Common.ICON_SMALL_CLIPBOARD));
System.Net.IPAddress ip = GetConnectedClientSocketIPAddressFor(remoteMachine);
- Common.LogDebug($"{nameof(ConnectToRemoteClipboardSocket)}Connecting to {remoteMachine}:{ip}:{sk.TcpPort}...");
+ Logger.LogDebug($"{nameof(ConnectToRemoteClipboardSocket)}Connecting to {remoteMachine}:{ip}:{sk.TcpPort}...");
if (ip != null)
{
@@ -917,7 +918,7 @@ namespace MouseWithoutBorders
clipboardTcpClient.Connect(remoteMachine, sk.TcpPort);
}
- Common.LogDebug($"Connected from {clipboardTcpClient.Client.LocalEndPoint}. Getting data...");
+ Logger.LogDebug($"Connected from {clipboardTcpClient.Client.LocalEndPoint}. Getting data...");
return clipboardTcpClient;
}
else
@@ -930,7 +931,7 @@ namespace MouseWithoutBorders
{
if (data == null || data.Length <= 0)
{
- Common.Log("data is null or empty!");
+ Logger.Log("data is null or empty!");
return;
}
@@ -988,28 +989,28 @@ namespace MouseWithoutBorders
if (txt.StartsWith("RTF", StringComparison.CurrentCultureIgnoreCase))
{
- Common.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of RTF <-");
+ Logger.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of RTF <-");
data1.SetData(DataFormats.Rtf, tmp);
}
else if (txt.StartsWith("HTM", StringComparison.CurrentCultureIgnoreCase))
{
- Common.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of HTM <-");
+ Logger.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of HTM <-");
data1.SetData(DataFormats.Html, tmp);
}
else if (txt.StartsWith("TXT", StringComparison.CurrentCultureIgnoreCase))
{
- Common.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of TXT <-");
+ Logger.LogDebug(((double)tmp.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of TXT <-");
data1.SetData(DataFormats.UnicodeText, tmp);
}
else
{
if (textTypeCount == 0)
{
- Common.LogDebug(((double)txt.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of UNI <-");
+ Logger.LogDebug(((double)txt.Length / 1024).ToString("0.00", CultureInfo.InvariantCulture) + "KB of UNI <-");
data1.SetData(DataFormats.UnicodeText, txt);
}
- Common.Log("Invalid clipboard format received!");
+ Logger.Log("Invalid clipboard format received!");
}
textTypeCount++;
@@ -1037,26 +1038,26 @@ namespace MouseWithoutBorders
SystemClipboard.SetFileDropList(filePaths);
return true;
},
- (log) => Common.TelemetryLogTrace(
+ (log) => Logger.TelemetryLogTrace(
log,
SeverityLevel.Information),
() => Common.LastClipboardEventTime = Common.GetTick());
}
catch (ExternalException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ThreadStateException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ArgumentNullException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ArgumentException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
});
}
@@ -1074,20 +1075,20 @@ namespace MouseWithoutBorders
SystemClipboard.SetImage(image);
return true;
},
- (log) => Common.TelemetryLogTrace(log, SeverityLevel.Information),
+ (log) => Logger.TelemetryLogTrace(log, SeverityLevel.Information),
() => Common.LastClipboardEventTime = Common.GetTick());
}
catch (ExternalException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ThreadStateException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ArgumentNullException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
});
}
@@ -1105,20 +1106,20 @@ namespace MouseWithoutBorders
SystemClipboard.SetText(text);
return true;
},
- (log) => Common.TelemetryLogTrace(log, SeverityLevel.Information),
+ (log) => Logger.TelemetryLogTrace(log, SeverityLevel.Information),
() => Common.LastClipboardEventTime = Common.GetTick());
}
catch (ExternalException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ThreadStateException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ArgumentNullException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
});
}
@@ -1134,15 +1135,15 @@ namespace MouseWithoutBorders
catch (ExternalException e)
{
string dataFormats = string.Join(",", dataObject.GetFormats());
- Common.Log($"{e.Message}: {dataFormats}");
+ Logger.Log($"{e.Message}: {dataFormats}");
}
catch (ThreadStateException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
catch (ArgumentNullException e)
{
- Common.Log(e);
+ Logger.Log(e);
}
});
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
index 11d9e5776d..f3ef0f1395 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
@@ -20,6 +20,7 @@ using Microsoft.PowerToys.Telemetry;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
namespace MouseWithoutBorders
{
@@ -73,12 +74,12 @@ namespace MouseWithoutBorders
MouseDown = true;
DragMachine = desMachineID;
dropMachineID = ID.NONE;
- LogDebug("DragDropStep01: MouseDown");
+ Logger.LogDebug("DragDropStep01: MouseDown");
}
else if (wParam == WM_LBUTTONUP)
{
MouseDown = false;
- LogDebug("DragDropStep01: MouseUp");
+ Logger.LogDebug("DragDropStep01: MouseUp");
}
if (wParam == WM_RBUTTONUP && IsDropping)
@@ -92,7 +93,7 @@ namespace MouseWithoutBorders
{
if (desMachineID == MachineID)
{
- LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent to myself");
+ Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent to myself");
DoSomethingInUIThread(() =>
{
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
@@ -101,7 +102,7 @@ namespace MouseWithoutBorders
else
{
SendCheckExplorerDragDrop();
- LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent");
+ Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent");
}
}
@@ -114,11 +115,11 @@ namespace MouseWithoutBorders
if (package.Des == MachineID || package.Des == ID.ALL)
{
- LogDebug("DragDropStep03: ExplorerDragDrop Received.");
+ Logger.LogDebug("DragDropStep03: ExplorerDragDrop Received.");
dropMachineID = package.Src; // Drop machine is the machine that sent ExplorerDragDrop
if (MouseDown || IsDropping)
{
- LogDebug("DragDropStep03: Mouse is down, check if dragging...sending WM_CHECK_EXPLORER_DRAG_DROP to myself...");
+ Logger.LogDebug("DragDropStep03: Mouse is down, check if dragging...sending WM_CHECK_EXPLORER_DRAG_DROP to myself...");
DoSomethingInUIThread(() =>
{
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
@@ -150,12 +151,12 @@ namespace MouseWithoutBorders
{
if (dragDropStep05ExCalledByIpc > 0)
{
- LogDebug("DragDropStep04: DragDropStep05ExCalledByIpc.");
+ Logger.LogDebug("DragDropStep04: DragDropStep05ExCalledByIpc.");
break;
}
_ = NativeMethods.GetCursorPos(ref p);
- LogDebug("DragDropStep04: Moving Mouse Without Borders Helper to (" + p.X.ToString(CultureInfo.CurrentCulture) + ", " + p.Y.ToString(CultureInfo.CurrentCulture) + ")");
+ Logger.LogDebug("DragDropStep04: Moving Mouse Without Borders Helper to (" + p.X.ToString(CultureInfo.CurrentCulture) + ", " + p.Y.ToString(CultureInfo.CurrentCulture) + ")");
_ = NativeMethods.SetWindowPos(h, NativeMethods.HWND_TOPMOST, p.X - 100 + i, p.Y - 100 + i, 200, 200, 0);
_ = NativeMethods.SendMessage(h, 0x000F, IntPtr.Zero, IntPtr.Zero); // WM_PAINT
Thread.Sleep(20);
@@ -166,20 +167,20 @@ namespace MouseWithoutBorders
}
else
{
- LogDebug("DragDropStep04: Mouse without Borders Helper not found!");
+ Logger.LogDebug("DragDropStep04: Mouse without Borders Helper not found!");
}
}
else
{
- LogDebug("DragDropStep04: IsDropping == true, skip checking");
+ Logger.LogDebug("DragDropStep04: IsDropping == true, skip checking");
}
- LogDebug("DragDropStep04: Got WM_CHECK_EXPLORER_DRAG_DROP, done with processing jump to DragDropStep05...");
+ Logger.LogDebug("DragDropStep04: Got WM_CHECK_EXPLORER_DRAG_DROP, done with processing jump to DragDropStep05...");
}
internal static void DragDropStep05Ex(string dragFileName)
{
- LogDebug("DragDropStep05 called.");
+ Logger.LogDebug("DragDropStep05 called.");
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 1);
@@ -204,21 +205,21 @@ namespace MouseWithoutBorders
}
DragDropStep06();
- LogDebug("DragDropStep05: File dragging: " + dragFileName);
+ Logger.LogDebug("DragDropStep05: File dragging: " + dragFileName);
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)1, (IntPtr)0);
}
else
{
- LogDebug("DragDropStep05: File not found: [" + dragFileName + "]");
+ Logger.LogDebug("DragDropStep05: File not found: [" + dragFileName + "]");
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)0, (IntPtr)0);
}
- LogDebug("DragDropStep05: WM_HIDE_DDHelper sent");
+ Logger.LogDebug("DragDropStep05: WM_HIDE_DDHelper sent");
});
}
else
{
- LogDebug("DragDropStep05: IsDropping == true, change drop machine...");
+ Logger.LogDebug("DragDropStep05: IsDropping == true, change drop machine...");
IsDropping = false;
MainFormVisible = true; // WM_HIDE_DRAG_DROP
SendDropBegin(); // To dropMachineID set in DragDropStep03
@@ -230,7 +231,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep06()
{
IsDragging = true;
- LogDebug("DragDropStep06: SendClipboardBeatDragDrop");
+ Logger.LogDebug("DragDropStep06: SendClipboardBeatDragDrop");
SendClipboardBeatDragDrop();
SendDropBegin();
}
@@ -238,7 +239,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep08(DATA package)
{
GetNameOfMachineWithClipboardData(package);
- LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set");
+ Logger.LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set");
}
internal static void DragDropStep08_2(DATA package)
@@ -247,7 +248,7 @@ namespace MouseWithoutBorders
{
IsDropping = true;
dropMachineID = MachineID;
- LogDebug("DragDropStep08_2: ClipboardDragDropOperation Received. IsDropping set");
+ Logger.LogDebug("DragDropStep08_2: ClipboardDragDropOperation Received. IsDropping set");
}
}
@@ -278,7 +279,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep10()
{
- LogDebug("DragDropStep10: Hide the form and get data...");
+ Logger.LogDebug("DragDropStep10: Hide the form and get data...");
IsDropping = false;
IsDragging = false;
LastIDWithClipboardData = ID.NONE;
@@ -294,7 +295,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep11()
{
- LogDebug("DragDropStep11: Mouse drag coming back, canceling drag/drop");
+ Logger.LogDebug("DragDropStep11: Mouse drag coming back, canceling drag/drop");
SendClipboardBeatDragDropEnd();
IsDropping = false;
IsDragging = false;
@@ -306,7 +307,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep12()
{
- LogDebug("DragDropStep12: ClipboardDragDropEnd received");
+ Logger.LogDebug("DragDropStep12: ClipboardDragDropEnd received");
IsDropping = false;
LastIDWithClipboardData = ID.NONE;
@@ -374,7 +375,7 @@ namespace MouseWithoutBorders
internal static void SendDropBegin()
{
- LogDebug("SendDropBegin...");
+ Logger.LogDebug("SendDropBegin...");
SendPackage(dropMachineID, PackageType.ClipboardDragDropOperation);
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs
index d557a8223c..1293a4ef39 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs
@@ -18,6 +18,8 @@ using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
+using MouseWithoutBorders.Core;
+
namespace MouseWithoutBorders
{
internal partial class Common
@@ -25,7 +27,9 @@ namespace MouseWithoutBorders
#pragma warning disable SYSLIB0021
private static AesCryptoServiceProvider symAl;
#pragma warning restore SYSLIB0021
- private static string myKey;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static string myKey;
+#pragma warning restore SA1307
private static uint magicNumber;
private static Random ran = new(); // Used for non encryption related functionality.
internal const int SymAlBlockSize = 16;
@@ -106,7 +110,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -189,7 +193,7 @@ namespace MouseWithoutBorders
hashValue = hash.ComputeHash(hashValue);
}
- Common.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1]));
+ Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1]));
hash.Clear();
return (uint)((hashValue[0] << 23) + (hashValue[1] << 16) + (hashValue[^1] << 8) + hashValue[2]);
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
index 7674ba2296..e50e87b8f9 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
@@ -18,6 +18,7 @@ using System.Threading.Tasks;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Form;
namespace MouseWithoutBorders
@@ -26,8 +27,10 @@ namespace MouseWithoutBorders
{
private static readonly DATA KeybdPackage = new();
private static readonly DATA MousePackage = new();
- private static ulong inputEventCount;
- private static ulong invalidPackageCount;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
+ internal static ulong inputEventCount;
+ internal static ulong invalidPackageCount;
+#pragma warning restore SA1307
internal static int MOVE_MOUSE_RELATIVE = 100000;
internal static int XY_BY_PIXEL = 300000;
@@ -73,7 +76,7 @@ namespace MouseWithoutBorders
{
HasSwitchedMachineSinceLastCopy = true;
- Common.LogDebug(string.Format(
+ Logger.LogDebug(string.Format(
CultureInfo.CurrentCulture,
"***** Host Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
newDesMachineIdEx,
@@ -117,7 +120,7 @@ namespace MouseWithoutBorders
if (actualLastPos != Common.LastPos)
{
- Common.LogDebug($"Mouse cursor has moved unexpectedly: Expected: {Common.LastPos}, actual: {actualLastPos}.");
+ Logger.LogDebug($"Mouse cursor has moved unexpectedly: Expected: {Common.LastPos}, actual: {actualLastPos}.");
Common.LastPos = actualLastPos;
}
}
@@ -138,7 +141,7 @@ namespace MouseWithoutBorders
}
catch (Exception ex)
{
- Log(ex);
+ Logger.Log(ex);
}
}
@@ -149,11 +152,11 @@ namespace MouseWithoutBorders
internal static void PrepareToSwitchToMachine(ID newDesMachineID, Point desMachineXY)
{
- LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
+ Logger.LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
if (((GetTick() - lastJump < 100) && (GetTick() - lastJump > 0)) || desMachineID == ID.ALL)
{
- LogDebug("PrepareToSwitchToMachine: lastJump");
+ Logger.LogDebug("PrepareToSwitchToMachine: lastJump");
return;
}
@@ -163,7 +166,7 @@ namespace MouseWithoutBorders
if (!IsConnectedTo(newDesMachineID))
{// Connection lost, cancel switching
- LogDebug("No active connection found for " + newDesMachineName);
+ Logger.LogDebug("No active connection found for " + newDesMachineName);
// ShowToolTip("No active connection found for [" + newDesMachineName + "]!", 500);
}
@@ -198,7 +201,7 @@ namespace MouseWithoutBorders
// Change des machine
if (desMachineID != newDesMachineID)
{
- LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
+ Logger.LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
// Ask current machine to hide the Mouse cursor
if (newDesMachineID != ID.ALL && desMachineID != MachineID)
@@ -246,7 +249,7 @@ namespace MouseWithoutBorders
PaintCount = 0;
if (desMachineID != newDesMachineID)
{
- LogDebug("KeybdEvent: Switching to new machine...");
+ Logger.LogDebug("KeybdEvent: Switching to new machine...");
DesMachineID = newDesMachineID;
}
@@ -265,7 +268,7 @@ namespace MouseWithoutBorders
}
catch (Exception ex)
{
- Log(ex);
+ Logger.Log(ex);
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs
index 12ee1810a8..ccbec57508 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs
@@ -22,7 +22,7 @@ using System.Windows.Forms;
//
using Microsoft.Win32;
using MouseWithoutBorders.Class;
-
+using MouseWithoutBorders.Core;
using static System.Windows.Forms.Control;
namespace MouseWithoutBorders
@@ -61,7 +61,7 @@ namespace MouseWithoutBorders
Process p = Process.GetCurrentProcess();
string procInfo = $"{p.PrivateMemorySize64 / 1024 / 1024}MB, {p.TotalProcessorTime}, {Environment.ProcessorCount}.";
string threadStacks = $"{procInfo} {Thread.DumpThreadsStack()}";
- Common.TelemetryLogTrace(threadStacks, SeverityLevel.Error);
+ Logger.TelemetryLogTrace(threadStacks, SeverityLevel.Error);
break;
}
@@ -95,7 +95,7 @@ namespace MouseWithoutBorders
Common.SwitchLocation.Count--;
// When we want to move mouse by pixels, we add 300k to x and y (search for XY_BY_PIXEL for other related code).
- Common.LogDebug($"+++++ Moving mouse to {Common.SwitchLocation.X}, {Common.SwitchLocation.Y}");
+ Logger.LogDebug($"+++++ Moving mouse to {Common.SwitchLocation.X}, {Common.SwitchLocation.Y}");
// MaxXY = 65535 so 100k is safe.
if (Common.SwitchLocation.X > XY_BY_PIXEL - 100000 || Common.SwitchLocation.Y > XY_BY_PIXEL - 100000)
@@ -119,16 +119,16 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
signalHelperToExit = false;
- LogDebug("^^^Helper Thread exiting...^^^");
+ Logger.LogDebug("^^^Helper Thread exiting...^^^");
}
internal static void MainFormDotEx(bool bCheckTS)
{
- LogDebug("***** MainFormDotEx:");
+ Logger.LogDebug("***** MainFormDotEx:");
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
@@ -178,7 +178,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
}
@@ -188,7 +188,7 @@ namespace MouseWithoutBorders
internal static void MainForm3Pixels()
{
- LogDebug("***** MainFormDotLarge:");
+ Logger.LogDebug("***** MainFormDotLarge:");
DoSomethingInUIThread(
() =>
@@ -254,7 +254,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -277,7 +277,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
_ = Common.SendMessageToHelper(SharedConst.QUIT_CMD, IntPtr.Zero, IntPtr.Zero);
}
@@ -291,7 +291,7 @@ namespace MouseWithoutBorders
if (!Common.IpcChannelCreated)
{
- TelemetryLogTrace($"{nameof(Common.IpcChannelCreated)} = {Common.IpcChannelCreated}. {GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"{nameof(Common.IpcChannelCreated)} = {Common.IpcChannelCreated}. {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
return;
}
@@ -317,12 +317,12 @@ namespace MouseWithoutBorders
var processes = Process.GetProcessesByName(HelperProcessName);
if (processes?.Length == 0)
{
- Log("Unable to start helper process.");
+ Logger.Log("Unable to start helper process.");
Common.ShowToolTip("Error starting Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
}
else
{
- Log("Helper process started.");
+ Logger.Log("Helper process started.");
}
}
else
@@ -330,11 +330,11 @@ namespace MouseWithoutBorders
var processes = Process.GetProcessesByName(HelperProcessName);
if (processes?.Length > 0)
{
- Log("Helper process found running.");
+ Logger.Log("Helper process found running.");
}
else
{
- Log("Invalid helper process found running.");
+ Logger.Log("Invalid helper process found running.");
Common.ShowToolTip("Error finding Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
}
}
@@ -354,7 +354,7 @@ namespace MouseWithoutBorders
if (log)
{
- Common.LogDebug($"SendMessageToHelper: HelperWindow={h}, Return={rv}, msg={msg}, w={wparam.ToInt32()}, l={lparam.ToInt32()}, Post={!wait}");
+ Logger.LogDebug($"SendMessageToHelper: HelperWindow={h}, Return={rv}, msg={msg}, w={wparam.ToInt32()}, l={lparam.ToInt32()}, Post={!wait}");
}
return rv;
@@ -424,7 +424,7 @@ namespace MouseWithoutBorders
log += "Last 10 trace messages:\r\n";
- log += string.Join(Environment.NewLine, LogCounter.Select(item => $"({item.Value}): {item.Key}").Take(10));
+ log += string.Join(Environment.NewLine, Logger.LogCounter.Select(item => $"({item.Value}): {item.Key}").Take(10));
log += "\r\n=============================================================================================================================";
@@ -447,7 +447,7 @@ namespace MouseWithoutBorders
Setting.Values.Username = Program.User;
}
- Common.LogDebug("[Username] = " + Setting.Values.Username);
+ Logger.LogDebug("[Username] = " + Setting.Values.Username);
}
return !string.IsNullOrEmpty(Setting.Values.Username);
@@ -490,7 +490,7 @@ Please use the keyboard and Mouse from the SAW device.
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
index 2c7f271b61..da52a60db2 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
@@ -19,6 +19,7 @@ using System.Threading;
//
using Microsoft.Win32;
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Form;
using Windows.UI.Input.Preview.Injection;
@@ -61,7 +62,7 @@ namespace MouseWithoutBorders
}
catch (Exception ex)
{
- Common.Log(ex);
+ Logger.Log(ex);
Common.MachinePool.Clear();
}
}
@@ -84,7 +85,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -102,13 +103,13 @@ namespace MouseWithoutBorders
{
Common.KeyCorrupted = true;
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
- Common.Log(e.Message);
+ Logger.Log(e.Message);
}
catch (CryptographicException e)
{
Common.KeyCorrupted = true;
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
- Common.Log(e.Message);
+ Logger.Log(e.Message);
}
try
@@ -123,7 +124,7 @@ namespace MouseWithoutBorders
catch (EntryPointNotFoundException)
{
NativeMethods.InjectMouseInputAvailable = false;
- Common.Log($"{nameof(NativeMethods.InjectMouseInputAvailable)} = false");
+ Logger.Log($"{nameof(NativeMethods.InjectMouseInputAvailable)} = false");
}
bool dummy = Setting.Values.DrawMouseEx;
@@ -149,7 +150,7 @@ namespace MouseWithoutBorders
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
{
- Common.TelemetryLogTrace($"{nameof(SystemEvents_PowerModeChanged)}: {e.Mode}", SeverityLevel.Information);
+ Logger.TelemetryLogTrace($"{nameof(SystemEvents_PowerModeChanged)}: {e.Mode}", SeverityLevel.Information);
LastResumeSuspendTime = DateTime.UtcNow;
SwitchToMultipleMode(false, true);
}
@@ -206,7 +207,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -230,13 +231,13 @@ namespace MouseWithoutBorders
VK.RCONTROL, VK.RMENU, VK.RWIN, VK.SHIFT, VK.MENU, VK.CONTROL,
};
- LogDebug("***** ReleaseAllKeys has been called! *****:");
+ Logger.LogDebug("***** ReleaseAllKeys has been called! *****:");
foreach (VK vk in keys)
{
if ((NativeMethods.GetAsyncKeyState((IntPtr)vk) & 0x8000) != 0)
{
- LogDebug(vk.ToString() + " is down, release it...");
+ Logger.LogDebug(vk.ToString() + " is down, release it...");
Hook?.ResetLastSwitchKeys(); // Sticky key can turn ALL PC mode on (CtrlCtrlCtrl)
kd.wVk = (int)vk;
InputSimulation.SendKey(kd);
@@ -247,7 +248,7 @@ namespace MouseWithoutBorders
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
- LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
+ Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
Common.WndProcCounter++;
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs
index 80ffe9fd84..5704e6119d 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs
@@ -19,6 +19,7 @@ using System.Security.Principal;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
namespace MouseWithoutBorders
{
@@ -44,17 +45,17 @@ namespace MouseWithoutBorders
{
dwSessionId = (uint)Process.GetCurrentProcess().SessionId;
uint rv = NativeMethods.WTSQueryUserToken(dwSessionId, ref hUserToken);
- LogDebug("WTSQueryUserToken returned " + rv.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("WTSQueryUserToken returned " + rv.ToString(CultureInfo.CurrentCulture));
if (rv == 0)
{
- LogDebug($"WTSQueryUserToken failed with: {Marshal.GetLastWin32Error()}.");
+ Logger.LogDebug($"WTSQueryUserToken failed with: {Marshal.GetLastWin32Error()}.");
return false;
}
if (!NativeMethods.DuplicateToken(hUserToken, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref hUserTokenDup))
{
- TelemetryLogTrace($"DuplicateToken Failed! {GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"DuplicateToken Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
_ = NativeMethods.CloseHandle(hUserToken);
_ = NativeMethods.CloseHandle(hUserTokenDup);
return false;
@@ -70,7 +71,7 @@ namespace MouseWithoutBorders
}
else
{
- Log("ImpersonateLoggedOnUser Failed!");
+ Logger.Log("ImpersonateLoggedOnUser Failed!");
_ = NativeMethods.CloseHandle(hUserToken);
_ = NativeMethods.CloseHandle(hUserTokenDup);
return false;
@@ -78,7 +79,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
return false;
}
}
@@ -102,7 +103,7 @@ namespace MouseWithoutBorders
int dwSessionId;
IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
- Common.LogDebug("CreateProcessInInputDesktopSession called, launching " + commandLineWithArg + " on " + desktop);
+ Logger.LogDebug("CreateProcessInInputDesktopSession called, launching " + commandLineWithArg + " on " + desktop);
try
{
@@ -122,7 +123,7 @@ namespace MouseWithoutBorders
if (!NativeMethods.DuplicateTokenEx(hUserToken, NativeMethods.MAXIMUM_ALLOWED, ref sa, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)NativeMethods.TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
{
lastError = Marshal.GetLastWin32Error();
- Common.Log(string.Format(CultureInfo.CurrentCulture, "DuplicateTokenEx error: {0} Token does not have the privilege.", lastError));
+ Logger.Log(string.Format(CultureInfo.CurrentCulture, "DuplicateTokenEx error: {0} Token does not have the privilege.", lastError));
_ = NativeMethods.CloseHandle(hUserToken);
return 0;
}
@@ -138,7 +139,7 @@ namespace MouseWithoutBorders
if (!rv)
{
- Log("ConvertStringSidToSid failed");
+ Logger.Log("ConvertStringSidToSid failed");
_ = NativeMethods.CloseHandle(hUserToken);
_ = NativeMethods.CloseHandle(hUserTokenDup);
return 0;
@@ -151,7 +152,7 @@ namespace MouseWithoutBorders
if (!rv)
{
- Log("SetTokenInformation failed");
+ Logger.Log("SetTokenInformation failed");
_ = NativeMethods.CloseHandle(hUserToken);
_ = NativeMethods.CloseHandle(hUserTokenDup);
return 0;
@@ -185,7 +186,7 @@ namespace MouseWithoutBorders
// GetLastError should be 0
int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
- LogDebug("CreateProcessAsUser returned " + iResultOfCreateProcessAsUser.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("CreateProcessAsUser returned " + iResultOfCreateProcessAsUser.ToString(CultureInfo.CurrentCulture));
// Close handles task
_ = NativeMethods.CloseHandle(hUserToken);
@@ -195,7 +196,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
return 0;
}
}
@@ -223,19 +224,19 @@ namespace MouseWithoutBorders
{
if ((p = Process.GetProcessById(processId)) == null)
{
- Log("Process exited!");
+ Logger.Log("Process exited!");
break;
}
}
catch (ArgumentException)
{
- Log("GetProcessById.ArgumentException");
+ Logger.Log("GetProcessById.ArgumentException");
break;
}
if ((!p.HasExited && p.PrivateMemorySize64 > limitedMem) || (++sec > (wait / 1000)))
{
- Log(string.Format(CultureInfo.CurrentCulture, "Process log (mem): {0}, {1}", sec, p.PrivateMemorySize64));
+ Logger.Log(string.Format(CultureInfo.CurrentCulture, "Process log (mem): {0}, {1}", sec, p.PrivateMemorySize64));
return false;
}
@@ -248,11 +249,11 @@ namespace MouseWithoutBorders
if ((p = Process.GetProcessById(processId)) == null)
{
- Log("Process exited!");
+ Logger.Log("Process exited!");
}
else if (NativeMethods.WaitForSingleObject(p.Handle, wait) != NativeMethods.WAIT_OBJECT_0 && killIfTimedOut)
{
- Log("Process log (time).");
+ Logger.Log("Process log (time).");
TerminateProcessTree(p.Handle, (uint)processId, -1);
return false;
}
@@ -287,12 +288,12 @@ namespace MouseWithoutBorders
}
catch (InvalidOperationException e)
{
- Log(e);
+ Logger.Log(e);
continue;
}
catch (Win32Exception e)
{
- Log(e);
+ Logger.Log(e);
continue;
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs
index 02e65d3891..df7518fdb5 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs
@@ -25,6 +25,7 @@ using System.Windows.Forms;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Exceptions;
namespace MouseWithoutBorders
@@ -81,7 +82,7 @@ namespace MouseWithoutBorders
internal static string DumpThreadsStack()
{
string stack = "\r\nMANAGED THREADS: " + threads.Count.ToString(CultureInfo.InvariantCulture) + "\r\n";
- stack += Common.GetStackTrace(new StackTrace());
+ stack += Logger.GetStackTrace(new StackTrace());
return stack;
}
@@ -115,385 +116,4 @@ namespace MouseWithoutBorders
internal System.Threading.ThreadState ThreadState => thread.ThreadState;
}
-
- internal partial class Common
- {
- private static readonly string[] AllLogs = new string[MAX_LOG];
- private static readonly object AllLogsLock = new();
- private static readonly ConcurrentDictionary LogCounter = new();
- private static readonly int[] RepeatedLogIndexSelection = new[] { 1, 3, 10, 50, 100 };
- private const int MAX_LOG = 10000;
- private static int allLogsIndex;
-
- private const int MaxLogExceptionPerHour = 1000;
- private static int lastHour;
- private static int exceptionCount;
-
- internal static void TelemetryLogTrace(string log, SeverityLevel severityLevel, bool flush = false)
- {
- int logCount = LogCounter.AddOrUpdate(log, 1, (key, value) => value + 1);
- Common.Log(log);
- }
-
- internal static void Log(Exception e)
- {
- if (e is not KnownException)
- {
- string exText = e.ToString();
-
- Log($"!Exception!: {exText}");
-
- if (DateTime.UtcNow.Hour != lastHour)
- {
- lastHour = DateTime.UtcNow.Hour;
- exceptionCount = 0;
- }
-
- if (exceptionCount < MaxLogExceptionPerHour)
- {
- exceptionCount++;
- }
- else if (exceptionCount != short.MaxValue)
- {
- exceptionCount = short.MaxValue;
- }
- }
- }
-
- private const string HeaderSENT =
- "Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}";
-
- private const string HeaderRECEIVED =
- "Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}";
-
- internal static void LogDebug(string log, bool clearLog = false)
- {
-#if DEBUG
- Log(log, clearLog);
-#endif
- }
-
- internal static void Log(string log, bool clearLog = false)
- {
- log = DateTime.Now.ToString("MM/dd HH:mm:ss.fff", CultureInfo.InvariantCulture) + $"({Thread.CurrentThread.ManagedThreadId})" + log;
-
- ManagedCommon.Logger.LogInfo(log);
- lock (AllLogsLock)
- {
- if (clearLog)
- {
- allLogsIndex = 0;
- }
-
- AllLogs[allLogsIndex] = log;
- allLogsIndex = (allLogsIndex + 1) % MAX_LOG;
- }
- }
-
- internal static void LogDebug(string format, params object[] args)
- {
-#if DEBUG
- Log(format, args);
-#endif
- }
-
- internal static void Log(string format, params object[] args)
- {
- Common.Log(string.Format(CultureInfo.InvariantCulture, format, args));
- }
-
- private static PackageMonitor p1;
- private static PackageMonitor p2;
-
- [Conditional("DEBUG")]
- internal static void LogAll()
- {
- string log;
-
- if (!p1.Equals(PackageSent))
- {
- log = string.Format(
- CultureInfo.CurrentCulture,
- "SENT:" + HeaderSENT,
- PackageSent.Heartbeat,
- PackageSent.Keyboard,
- PackageSent.Mouse,
- PackageSent.Hello,
- PackageSent.Matrix,
- PackageSent.ClipboardText,
- PackageSent.ClipboardImage,
- PackageSent.ByeBye,
- PackageSent.Clipboard,
- PackageSent.ClipboardDragDrop,
- PackageSent.ClipboardDragDropEnd,
- PackageSent.ExplorerDragDrop,
- inputEventCount,
- PackageSent.Nil);
- Log(log);
- p1 = PackageSent; // Copy data
- }
-
- if (!p2.Equals(PackageReceived))
- {
- log = string.Format(
- CultureInfo.CurrentCulture,
- "RECEIVED:" + HeaderRECEIVED,
- PackageReceived.Heartbeat,
- PackageReceived.Keyboard,
- PackageReceived.Mouse,
- PackageReceived.Hello,
- PackageReceived.Matrix,
- PackageReceived.ClipboardText,
- PackageReceived.ClipboardImage,
- PackageReceived.ByeBye,
- PackageReceived.Clipboard,
- PackageReceived.ClipboardDragDrop,
- PackageReceived.ClipboardDragDropEnd,
- PackageReceived.ExplorerDragDrop,
- invalidPackageCount,
- PackageReceived.Nil,
- processedPackageCount,
- skippedPackageCount);
- Log(log);
- p2 = PackageReceived;
- }
- }
-
- internal static void GenerateLog()
- {
- int l = Setting.Values.DumpObjectsLevel;
- if (l is > 0 and < 10)
- {
- Common.DumpObjects(l);
- }
- }
-
- private static List myThreads;
-
- internal static void DumpObjects(int level)
- {
- try
- {
- string logFile = Path.Combine(Common.RunWithNoAdminRight ? Path.GetTempPath() : Path.GetDirectoryName(Application.ExecutablePath), "MagicMouse.log");
-
- StringBuilder sb = new(1000000);
- string log;
-
- myThreads = new List();
-
- foreach (ProcessThread t in Process.GetCurrentProcess().Threads)
- {
- myThreads.Add(t);
- }
-
- _ = PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
- _ = PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
-
- log = string.Format(
- CultureInfo.CurrentCulture,
- "{0} {1}\r\n{2}\r\n\r\n{3}",
- Application.ProductName,
- Application.ProductVersion,
- "Private Mem: " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString(CultureInfo.CurrentCulture) + "KB",
- sb.ToString());
-
- if (!string.IsNullOrEmpty(myKey))
- {
- log = log.Replace(MyKey, GetDebugInfo(MyKey));
- }
-
- log += Thread.DumpThreadsStack();
- log += $"\r\nCurrent process session: {Process.GetCurrentProcess().SessionId}, active console session: {NativeMethods.WTSGetActiveConsoleSessionId()}.";
-
- File.WriteAllText(logFile, log);
-
- if (RunOnLogonDesktop || RunOnScrSaverDesktop)
- {
- _ = MessageBox.Show("Dump file created: " + logFile, Application.ProductName);
- }
- else
- {
- ShowToolTip("Dump file created: " + logFile + " and placed in the Clipboard.", 10000);
- Clipboard.SetText(logFile);
- }
- }
- catch (Exception e)
- {
- _ = MessageBox.Show(e.Message + "\r\n" + e.StackTrace, Application.ProductName);
- }
- }
-
- private static object GetFieldValue(object obj, string fieldName)
- {
- FieldInfo fi;
- Type t;
-
- t = obj.GetType();
- fi = t.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
- return fi?.GetValue(obj);
- }
-
- private static bool PrivateDump(StringBuilder sb, object obj, string objName, int level, int maxLevel, bool stop)
- {
- Type t;
- string padStr = string.Empty;
- string[] strArr;
- string objString;
-
- if (obj == null || (maxLevel >= 0 && level >= maxLevel) || obj is Cursor)
- {
- return false;
- }
-
- for (int i = 0; i < level; i++)
- {
- padStr += i < level - 1 ? "-" : padStr += string.Empty;
- }
-
- objString = obj.ToString();
- t = obj.GetType();
- strArr = new string[7];
- strArr[0] = padStr;
- strArr[1] = objName;
-
- // strArr[2] = " ";
- // strArr[3] = t.FullName;
- strArr[4] = " = ";
- strArr[5] = objName.Equals("myKey", StringComparison.OrdinalIgnoreCase) ? GetDebugInfo(objString)
- : objName.Equals("lastClipboardObject", StringComparison.OrdinalIgnoreCase) ? string.Empty
- : objString.Replace("System.Windows.Forms.", string.Empty).Replace("System.Net.Sockets.", string.Empty).Replace("System.Security.Cryptography.", string.Empty).Replace("System.Threading.", string.Empty)
- .Replace("System.ComponentModel.", string.Empty).Replace("System.Runtime.", string.Empty).Replace("System.Drawing.", string.Empty).Replace("System.Object", "O").Replace("System.Diagnostics.", string.Empty)
- .Replace("System.Collections.", string.Empty).Replace("System.Drawing.", string.Empty).Replace("System.Int", string.Empty).Replace("System.EventHandler.", string.Empty);
- strArr[6] = "\r\n";
- _ = sb.Append(string.Concat(strArr).Replace(Common.BinaryName, "MM"));
-
- if (stop || t.IsPrimitive)
- {
- return false;
- }
-
- DumpType(padStr, sb, obj, level, t, maxLevel);
- return true;
- }
-
- private static void DumpType(string initialStr, StringBuilder sb, object obj, int level, System.Type t, int maxLevel)
- {
- int i;
- bool stop;
- if (t == typeof(System.Delegate))
- {
- return;
- }
-
- FieldInfo[] fi;
- string type;
-
- if (obj is MouseWithoutBorders.PackageType or string or AddressFamily or ID or IPAddress
- )
- {
- return;
- }
-
- type = obj.GetType().ToString();
-
- if (type.EndsWith("type", StringComparison.CurrentCultureIgnoreCase) || type.Contains("Cryptography")
- || type.EndsWith("AsyncEventBits", StringComparison.CurrentCultureIgnoreCase))
- {
- return;
- }
-
- stop = obj == null || obj is MouseWithoutBorders.DATA || obj.GetType().BaseType == typeof(ValueType)
- || obj.GetType().Namespace.Contains("System.Windows");
- fi = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
-
- foreach (FieldInfo f in fi)
- {
- if (f.GetValue(obj) != AllLogs)
- {
- _ = PrivateDump(sb, f.GetValue(obj), f.Name, level + 1, maxLevel, stop);
- }
- }
-
- if (obj is Dictionary>)
- {
- Dictionary> d = obj as Dictionary>;
-
- foreach (string k in d.Keys)
- {
- if (d.TryGetValue(k, out List l))
- {
- foreach (IPAddress ip in l)
- {
- _ = PrivateDump(sb, ip, "[" + k + "]", level + 1, maxLevel, false);
- }
- }
- }
- }
-
- if (obj is System.Array)
- {
- try
- {
- if (obj is MachineInf[])
- {
- MachineInf[] os = (MachineInf[])obj;
-
- for (i = 0; i < os.GetLength(0); i++)
- {
- _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
- }
- }
- else if (obj is int[] || obj is uint[])
- {
- int[] os = (int[])obj;
-
- for (i = 0; i < os.GetLength(0); i++)
- {
- _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
- }
- }
- else if (obj is short[] || obj is ushort[])
- {
- short[] os = (short[])obj;
-
- for (i = 0; i < os.GetLength(0); i++)
- {
- _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
- }
- }
- else if (obj is TcpClient[] || obj is IPAddress[] || obj is TcpSk[] || obj is string[]
- || obj is TcpServer[]
- || obj is ProcessThread[] || obj is Thread[])
- {
- object[] os = (object[])obj;
-
- for (i = 0; i < os.GetLength(0); i++)
- {
- _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
- }
- }
- else
- {
- _ = PrivateDump(sb, obj.GetType().ToString() + ": N/A", obj.GetType().ToString(), level + 1, maxLevel, false);
- }
- }
- catch (Exception)
- {
- }
- }
- }
-
- internal static string GetStackTrace(StackTrace st)
- {
- string rv = string.Empty;
-
- for (int i = 0; i < st.FrameCount; i++)
- {
- StackFrame sf = st.GetFrame(i);
- rv += sf.GetMethod() + " <= ";
- }
-
- return rv;
- }
- }
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
index d2f79e931f..2088fa0b8f 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
@@ -22,6 +22,7 @@ using Microsoft.PowerToys.Telemetry;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
namespace MouseWithoutBorders
{
@@ -390,7 +391,7 @@ namespace MouseWithoutBorders
// THIS LOGIC IS THE SAME FOR Move*(int x, int y) METHODS.
if (newDesMachineIdEx != desMachineID)
{
- LogDebug("Move Right");
+ Logger.LogDebug("Move Right");
if (!Setting.Values.MoveMouseRelatively)
{
@@ -529,7 +530,7 @@ namespace MouseWithoutBorders
if (newDesMachineIdEx != desMachineID)
{
- LogDebug("Move Left");
+ Logger.LogDebug("Move Left");
return !Setting.Values.MoveMouseRelatively
? newDesMachineIdEx == MachineID
@@ -598,7 +599,7 @@ namespace MouseWithoutBorders
if (newDesMachineIdEx != desMachineID)
{
- LogDebug("Move Up");
+ Logger.LogDebug("Move Up");
return !Setting.Values.MoveMouseRelatively
? newDesMachineIdEx == MachineID
@@ -668,7 +669,7 @@ namespace MouseWithoutBorders
if (newDesMachineIdEx != desMachineID)
{
- LogDebug("Move Down");
+ Logger.LogDebug("Move Down");
return !Setting.Values.MoveMouseRelatively
? newDesMachineIdEx == MachineID
@@ -696,7 +697,7 @@ namespace MouseWithoutBorders
rv = true;
}
- LogDebug("<><><><><>>><><><<><><><><><><><><><><>><><><><><><><><><><><" + inf.Name);
+ Logger.LogDebug("<><><><><>>><><><<><><><><><><><><><><>><><><><><><><><><><><" + inf.Name);
}
}
@@ -740,7 +741,7 @@ namespace MouseWithoutBorders
if (machineInfo.Name.Equals(DesMachineName, StringComparison.OrdinalIgnoreCase))
{
- LogDebug("AddToMachinePool: Des ID updated: " + DesMachineID.ToString() + "/" + package.Src.ToString());
+ Logger.LogDebug("AddToMachinePool: Des ID updated: " + DesMachineID.ToString() + "/" + package.Src.ToString());
newDesMachineID = desMachineID = package.Src;
}
@@ -754,7 +755,7 @@ namespace MouseWithoutBorders
}
else
{
- LogDebug("AddToMachinePool: could not add a new machine: " + name);
+ Logger.LogDebug("AddToMachinePool: could not add a new machine: " + name);
return "The 5th machine";
}
}
@@ -781,14 +782,14 @@ namespace MouseWithoutBorders
Common.ReopenSockets(true);
Common.SendMachineMatrix();
- LogDebug("Machine added: " + name + "/" + package.Src.ToString());
+ Logger.LogDebug("Machine added: " + name + "/" + package.Src.ToString());
UpdateClientSockets("AddToMachinePool");
return name;
}
internal static void UpdateClientSockets(string logHeader)
{
- LogDebug("UpdateClientSockets: " + logHeader);
+ Logger.LogDebug("UpdateClientSockets: " + logHeader);
Sk?.UpdateTCPClients();
}
@@ -802,13 +803,13 @@ namespace MouseWithoutBorders
internal static void ShowSetupForm(bool reopenSockets = false)
{
- Common.LogDebug("========== BEGIN THE SETUP EXPERIENCE ==========", true);
+ Logger.LogDebug("========== BEGIN THE SETUP EXPERIENCE ==========", true);
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
Common.GeneratedKey = true;
if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
- Common.Log("Not physical console session.");
+ Logger.Log("Not physical console session.");
_ = MessageBox.Show(
"Please run the program in the physical console session.\r\nThe program does not work in a remote desktop or virtual machine session.",
Application.ProductName,
@@ -948,7 +949,7 @@ namespace MouseWithoutBorders
{
bool twoRow = !Setting.Values.MatrixOneRow;
string[] connectedMachines = twoRow ? MachineMatrix : MachineMatrix.Select(m => IsConnectedTo(IdFromName(m)) ? m : string.Empty).ToArray();
- LogDebug($"Matrix: {string.Join(",", MachineMatrix)}, Connected: {string.Join(",", connectedMachines)}");
+ Logger.LogDebug($"Matrix: {string.Join(",", MachineMatrix)}, Connected: {string.Join(",", connectedMachines)}");
return connectedMachines;
}
@@ -981,7 +982,7 @@ namespace MouseWithoutBorders
SkSend(package, null, false);
- LogDebug($"matrixIncludedMachine sent: [{i + 1}]:[{MachineMatrix[i]}]");
+ Logger.LogDebug($"matrixIncludedMachine sent: [{i + 1}]:[{MachineMatrix[i]}]");
}
}
@@ -992,7 +993,7 @@ namespace MouseWithoutBorders
if (i is > 0 and <= MAX_MACHINE)
{
- LogDebug($"matrixIncludedMachine: [{i}]:[{matrixIncludedMachine}]");
+ Logger.LogDebug($"matrixIncludedMachine: [{i}]:[{matrixIncludedMachine}]");
MachineMatrix[i - 1] = matrixIncludedMachine;
@@ -1011,7 +1012,7 @@ namespace MouseWithoutBorders
}
else
{
- LogDebug("Invalid machine Matrix package!");
+ Logger.LogDebug("Invalid machine Matrix package!");
}
}
@@ -1080,7 +1081,7 @@ namespace MouseWithoutBorders
if (!created)
{
- TelemetryLogTrace($"Second instance found: {eventName}.", SeverityLevel.Warning, true);
+ Logger.TelemetryLogTrace($"Second instance found: {eventName}.", SeverityLevel.Warning, true);
CurrentProcess.KillProcess(true);
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs
index b4d2af42f4..5b17801450 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs
@@ -20,6 +20,7 @@ using System.Windows.Forms;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
[module: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "MouseWithoutBorders.Common.#PreProcess(MouseWithoutBorders.DATA)", Justification = "Dotnet port with style preservation")]
@@ -30,8 +31,10 @@ namespace MouseWithoutBorders
private static readonly uint QUEUE_SIZE = 50;
private static readonly int[] RecentProcessedPackageIDs = new int[QUEUE_SIZE];
private static int recentProcessedPackageIndex;
- private static long processedPackageCount;
- private static long skippedPackageCount;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static long processedPackageCount;
+ internal static long skippedPackageCount;
+#pragma warning restore SA1307
internal static long JustGotAKey { get; set; }
@@ -45,12 +48,12 @@ namespace MouseWithoutBorders
}
Common.InvalidPackageCount++;
- Common.Log("Invalid packages received!");
+ Logger.Log("Invalid packages received!");
return false;
}
else if (package.Type == 0)
{
- Common.Log("Got an unknown package!");
+ Logger.Log("Got an unknown package!");
return false;
}
else if (package.Type is not PackageType.ClipboardText and not PackageType.ClipboardImage
@@ -157,7 +160,7 @@ namespace MouseWithoutBorders
{
HasSwitchedMachineSinceLastCopy = true;
- Common.LogDebug(string.Format(
+ Logger.LogDebug(string.Format(
CultureInfo.CurrentCulture,
"***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
newDesMachineIdEx,
@@ -191,7 +194,7 @@ namespace MouseWithoutBorders
break;
case PackageType.NextMachine:
- LogDebug("PackageType.NextMachine received!");
+ Logger.LogDebug("PackageType.NextMachine received!");
if (IsSwitchingByMouseEnabled())
{
@@ -334,7 +337,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
});
}
@@ -395,7 +398,7 @@ namespace MouseWithoutBorders
else
{
// We should never get to this point!
- Common.Log("Invalid package received!");
+ Logger.Log("Invalid package received!");
return;
}
}
@@ -421,7 +424,7 @@ namespace MouseWithoutBorders
private static void SignalBigClipboardData()
{
- LogDebug("SignalBigClipboardData");
+ Logger.LogDebug("SignalBigClipboardData");
SetToggleIcon(new int[TOGGLE_ICONS_SIZE] { ICON_BIG_CLIPBOARD, -1, ICON_BIG_CLIPBOARD, -1 });
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs
index 1b65270fd0..a5a71baf5c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs
@@ -21,6 +21,7 @@ using System.Windows.Forms;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.Common.#StartMouseWithoutBordersService()", Justification = "Dotnet port with style preservation")]
@@ -39,7 +40,7 @@ namespace MouseWithoutBorders
return;
}
- Log($"{nameof(StartMouseWithoutBordersService)}: {GetStackTrace(new StackTrace())}.");
+ Logger.Log($"{nameof(StartMouseWithoutBordersService)}: {Logger.GetStackTrace(new StackTrace())}.");
Task task = Task.Run(() =>
{
@@ -49,13 +50,13 @@ namespace MouseWithoutBorders
{
if (DateTime.UtcNow - lastStartServiceTime < TimeSpan.FromSeconds(5))
{
- Log($"{nameof(StartMouseWithoutBordersService)}: Aborted.");
+ Logger.Log($"{nameof(StartMouseWithoutBordersService)}: Aborted.");
return;
}
foreach (Process pp in ps)
{
- Common.Log(string.Format(CultureInfo.InvariantCulture, "Killing process MouseWithoutBordersSvc {0}.", pp.Id));
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process MouseWithoutBordersSvc {0}.", pp.Id));
pp.KillProcess();
}
}
@@ -65,7 +66,7 @@ namespace MouseWithoutBorders
try
{
- Log("Starting " + service.ServiceName);
+ Logger.Log("Starting " + service.ServiceName);
}
catch (Exception)
{
@@ -104,7 +105,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
// ERROR_SERVICE_ALREADY_RUNNING
if (!(shownErrMessage || ((e?.InnerException as Win32Exception)?.NativeErrorCode == 1056)))
@@ -153,7 +154,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log($"{nameof(StartServiceAndSendLogoffSignal)}: {e.Message}");
+ Logger.Log($"{nameof(StartServiceAndSendLogoffSignal)}: {e.Message}");
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs b/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs
index 96b605c5b1..7c0dd4eb9b 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs
@@ -3,26 +3,30 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Diagnostics;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
+using MouseWithoutBorders.Class;
+
+using Logger = MouseWithoutBorders.Core.Logger;
namespace MouseWithoutBorders
{
internal class ShutdownWithPowerToys
{
- public static void WaitForPowerToysRunner()
+ public static void WaitForPowerToysRunner(ETWTrace etwTrace)
{
try
{
RunnerHelper.WaitForPowerToysRunnerExitFallback(() =>
{
+ etwTrace?.Dispose();
Common.MainForm.Quit(true, false);
});
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
index 775945cc34..722590ef81 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
@@ -21,6 +21,7 @@ using System.Windows.Forms;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
namespace MouseWithoutBorders
{
@@ -52,19 +53,19 @@ namespace MouseWithoutBorders
{
// For logging only
_ = NativeMethods.GetDpiForMonitor(hMonitor, 0, out uint dpiX, out uint dpiY);
- Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY));
+ Logger.Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY));
}
catch (DllNotFoundException)
{
- Common.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
+ Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (EntryPointNotFoundException)
{
- Common.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
+ Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
if (mi.rcMonitor.Left == 0 && mi.rcMonitor.Top == 0 && mi.rcMonitor.Right != 0 && mi.rcMonitor.Bottom != 0)
@@ -116,7 +117,7 @@ namespace MouseWithoutBorders
{
try
{
- Common.LogDebug("==================== GetScreenConfig started");
+ Logger.LogDebug("==================== GetScreenConfig started");
newDesktopBounds = new MyRectangle();
newPrimaryScreenBounds = new MyRectangle();
newDesktopBounds.Left = newPrimaryScreenBounds.Left = Screen.PrimaryScreen.Bounds.Left;
@@ -124,7 +125,7 @@ namespace MouseWithoutBorders
newDesktopBounds.Right = newPrimaryScreenBounds.Right = Screen.PrimaryScreen.Bounds.Right;
newDesktopBounds.Bottom = newPrimaryScreenBounds.Bottom = Screen.PrimaryScreen.Bounds.Bottom;
- Common.Log(string.Format(
+ Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
@@ -162,7 +163,7 @@ namespace MouseWithoutBorders
Interlocked.Exchange(ref desktopBounds, newDesktopBounds);
Interlocked.Exchange(ref primaryScreenBounds, newPrimaryScreenBounds);
- Common.Log(string.Format(
+ Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
@@ -175,11 +176,11 @@ namespace MouseWithoutBorders
Common.DesktopBounds.Right,
Common.DesktopBounds.Bottom));
- Common.Log("==================== GetScreenConfig ended");
+ Logger.Log("==================== GetScreenConfig ended");
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -265,7 +266,7 @@ namespace MouseWithoutBorders
{
if (!Common.RunWithNoAdminRight)
{
- LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
+ Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
}
}
@@ -282,19 +283,19 @@ namespace MouseWithoutBorders
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
{
waitCount--;
- LogDebug("The session is detached/attached.");
+ Logger.LogDebug("The session is detached/attached.");
Thread.Sleep(500);
}
string myDesktop = GetMyDesktop();
activeDesktop = GetInputDesktop();
- LogDebug("*** Active Desktop = " + activeDesktop);
- LogDebug("*** My Desktop = " + myDesktop);
+ Logger.LogDebug("*** Active Desktop = " + activeDesktop);
+ Logger.LogDebug("*** My Desktop = " + myDesktop);
if (myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
- LogDebug("*** Active Desktop == My Desktop (TS session)");
+ Logger.LogDebug("*** Active Desktop == My Desktop (TS session)");
}
if (!activeDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
@@ -307,25 +308,25 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}");
+ Logger.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}");
}
}
else
{
if (!myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
- Log("*** Active Desktop <> My Desktop");
+ Logger.Log("*** Active Desktop <> My Desktop");
}
uint sid = NativeMethods.WTSGetActiveConsoleSessionId();
if (Process.GetProcessesByName(Common.BinaryName).Any(p => (uint)p.SessionId == sid))
{
- Log("Found MouseWithoutBorders on the active session!");
+ Logger.Log("Found MouseWithoutBorders on the active session!");
}
else
{
- Log("MouseWithoutBorders not found on the active session!");
+ Logger.Log("MouseWithoutBorders not found on the active session!");
StartMMService(null);
}
}
@@ -333,7 +334,7 @@ namespace MouseWithoutBorders
if (!myDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
!myDesktop.Equals("default", StringComparison.OrdinalIgnoreCase))
{
- LogDebug("*** Desktop inactive, exiting: " + myDesktop);
+ Logger.LogDebug("*** Desktop inactive, exiting: " + myDesktop);
Setting.Values.LastX = JUST_GOT_BACK_FROM_SCREEN_SAVER;
if (cleanupIfExit)
{
@@ -346,7 +347,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs
index 325f84ca7d..1caeb47b2c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs
@@ -29,6 +29,7 @@ using Microsoft.PowerToys.Settings.UI.Library;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Exceptions;
// Log is enough
@@ -78,7 +79,7 @@ namespace MouseWithoutBorders
{
internal partial class Common
{
- private Common()
+ internal Common()
{
}
@@ -259,7 +260,7 @@ namespace MouseWithoutBorders
{
if (SocketMutex != null)
{
- LogDebug("SOCKET MUTEX BEGIN RELEASE.");
+ Logger.LogDebug("SOCKET MUTEX BEGIN RELEASE.");
try
{
@@ -269,14 +270,14 @@ namespace MouseWithoutBorders
catch (ApplicationException e)
{
// The current thread does not own the mutex, the thread acquired it will own it.
- TelemetryLogTrace($"{nameof(ReleaseSocketMutex)}: {e.Message}. {Thread.CurrentThread.ManagedThreadId}/{UIThreadID}.", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"{nameof(ReleaseSocketMutex)}: {e.Message}. {Thread.CurrentThread.ManagedThreadId}/{UIThreadID}.", SeverityLevel.Warning);
}
- LogDebug("SOCKET MUTEX RELEASED.");
+ Logger.LogDebug("SOCKET MUTEX RELEASED.");
}
else
{
- LogDebug("SOCKET MUTEX NULL.");
+ Logger.LogDebug("SOCKET MUTEX NULL.");
}
}
@@ -284,7 +285,7 @@ namespace MouseWithoutBorders
{
if (SocketMutex != null)
{
- LogDebug("SOCKET MUTEX BEGIN WAIT.");
+ Logger.LogDebug("SOCKET MUTEX BEGIN WAIT.");
int waitTimeout = 60000; // TcpListener.Stop may take very long to complete for some reason.
int socketMutexBalance = int.MinValue;
@@ -302,14 +303,14 @@ namespace MouseWithoutBorders
if (!acquireMutex)
{
Process[] ps = Process.GetProcessesByName(Common.BinaryName);
- TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {GetMyDesktop()}/{GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {GetMyDesktop()}/{GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning);
}
- LogDebug("SOCKET MUTEX ENDED.");
+ Logger.LogDebug("SOCKET MUTEX ENDED.");
}
else
{
- LogDebug("SOCKET MUTEX NULL.");
+ Logger.LogDebug("SOCKET MUTEX NULL.");
}
}
@@ -318,7 +319,7 @@ namespace MouseWithoutBorders
internal static bool ExecuteAndTrace(string actionName, Action action, TimeSpan timeout, bool restart = false)
{
bool rv = true;
- LogDebug(actionName);
+ Logger.LogDebug(actionName);
bool done = false;
BlockingUI = true;
@@ -343,12 +344,12 @@ namespace MouseWithoutBorders
}
}
- TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}, restarting the process.", SeverityLevel.Warning, true);
+ Logger.TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}, restarting the process.", SeverityLevel.Warning, true);
string desktop = Common.GetMyDesktop();
oneInstanceCheck?.Close();
_ = Process.Start(Application.ExecutablePath, desktop);
- LogDebug($"Started on desktop {desktop}");
+ Logger.LogDebug($"Started on desktop {desktop}");
Process.GetCurrentProcess().KillProcess(true);
},
@@ -379,7 +380,7 @@ namespace MouseWithoutBorders
if (!restart)
{
- TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}: {(long)timer.Elapsed.TotalSeconds}.", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}: {(long)timer.Elapsed.TotalSeconds}.", SeverityLevel.Warning);
}
}
}
@@ -445,7 +446,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
finally
{
@@ -457,7 +458,7 @@ namespace MouseWithoutBorders
catch (Exception e)
{
done = true;
- Log(e);
+ Logger.Log(e);
}
while (blocking && !done)
@@ -508,11 +509,11 @@ namespace MouseWithoutBorders
internal static void SendNextMachine(ID hostMachine, ID nextMachine, Point requestedXY)
{
- LogDebug($"SendNextMachine: Host machine: {hostMachine}, Next machine: {nextMachine}, Requested XY: {requestedXY}");
+ Logger.LogDebug($"SendNextMachine: Host machine: {hostMachine}, Next machine: {nextMachine}, Requested XY: {requestedXY}");
if (GetTick() - lastSendNextMachine < 100)
{
- LogDebug("Machine switching in progress."); // "Move Mouse relatively" mode, slow machine/network, quick/busy hand.
+ Logger.LogDebug("Machine switching in progress."); // "Move Mouse relatively" mode, slow machine/network, quick/busy hand.
return;
}
@@ -529,7 +530,7 @@ namespace MouseWithoutBorders
SkSend(package, null, false);
- LogDebug("SendNextMachine done.");
+ Logger.LogDebug("SendNextMachine done.");
}
private static ulong lastInputEventCount;
@@ -603,7 +604,7 @@ namespace MouseWithoutBorders
private static void SendByeBye()
{
- LogDebug($"{nameof(SendByeBye)}");
+ Logger.LogDebug($"{nameof(SendByeBye)}");
SendPackage(ID.ALL, PackageType.ByeBye);
}
@@ -629,7 +630,7 @@ namespace MouseWithoutBorders
internal static void SetToggleIcon(int[] toggleIcons)
{
- Common.LogDebug($"{nameof(SetToggleIcon)}: {toggleIcons?.FirstOrDefault()}");
+ Logger.LogDebug($"{nameof(SetToggleIcon)}: {toggleIcons?.FirstOrDefault()}");
Common.toggleIcons = toggleIcons;
toggleIconsIndex = 0;
}
@@ -651,7 +652,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
return null;
}
}
@@ -666,7 +667,7 @@ namespace MouseWithoutBorders
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
InputSimulation.SendKey(new KEYBDDATA() { dwFlags = (int)Common.LLKHF.UP, wVk = (int)VK.SNAPSHOT });
- Common.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
+ Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
_ = NativeMethods.MoveWindow(
(IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT),
@@ -680,7 +681,7 @@ namespace MouseWithoutBorders
}
else
{
- Common.Log("PrepareScreenCapture: Validation failed.");
+ Logger.Log("PrepareScreenCapture: Validation failed.");
}
});
}
@@ -761,7 +762,7 @@ namespace MouseWithoutBorders
}
else
{
- Log(tip);
+ Logger.Log(tip);
}
}
});
@@ -934,7 +935,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
t.BackingSocket = null; // To be removed at CloseAnUnusedSocket()
updateClientSockets = true;
}
@@ -945,7 +946,7 @@ namespace MouseWithoutBorders
if (!connected && data.Des != ID.ALL)
{
- LogDebug("********** No active connection found for the remote machine! **********" + data.Des.ToString());
+ Logger.LogDebug("********** No active connection found for the remote machine! **********" + data.Des.ToString());
if (data.Des == ID.NONE || RemoveDeadMachines(data.Des))
{
@@ -965,7 +966,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
#if DEBUG
@@ -1006,7 +1007,7 @@ namespace MouseWithoutBorders
{
if ((t.Status != SocketStatus.Connected && t.BirthTime < GetTick() - SocketStuff.CONNECT_TIMEOUT) || t.BackingSocket == null)
{
- LogDebug("CloseAnUnusedSocket: " + t.MachineName + ":" + t.MachineId + "|" + t.Status.ToString());
+ Logger.LogDebug("CloseAnUnusedSocket: " + t.MachineName + ":" + t.MachineId + "|" + t.Status.ToString());
tobeRemoved = t;
if (t.BackingSocket != null)
@@ -1017,7 +1018,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
}
}
@@ -1048,7 +1049,7 @@ namespace MouseWithoutBorders
{
if (t.Status == SocketStatus.Connected)
{
- LogDebug("AtLeastOneSocketConnected returning true: " + t.MachineName);
+ Logger.LogDebug("AtLeastOneSocketConnected returning true: " + t.MachineName);
return true;
}
}
@@ -1056,7 +1057,7 @@ namespace MouseWithoutBorders
}
}
- LogDebug("AtLeastOneSocketConnected returning false.");
+ Logger.LogDebug("AtLeastOneSocketConnected returning false.");
return false;
}
@@ -1074,7 +1075,7 @@ namespace MouseWithoutBorders
{
if (!t.IsClient && t.Status == SocketStatus.Connected)
{
- LogDebug("AtLeastOneServerSocketConnected returning true: " + t.MachineName);
+ Logger.LogDebug("AtLeastOneServerSocketConnected returning true: " + t.MachineName);
return t.BackingSocket;
}
}
@@ -1082,7 +1083,7 @@ namespace MouseWithoutBorders
}
}
- LogDebug("AtLeastOneServerSocketConnected returning false.");
+ Logger.LogDebug("AtLeastOneServerSocketConnected returning false.");
return null;
}
@@ -1119,7 +1120,7 @@ namespace MouseWithoutBorders
{
if (TestSend(t))
{
- LogDebug($"{nameof(AtLeastOneSocketEstablished)} returning true: {t.MachineName}");
+ Logger.LogDebug($"{nameof(AtLeastOneSocketEstablished)} returning true: {t.MachineName}");
return true;
}
}
@@ -1128,7 +1129,7 @@ namespace MouseWithoutBorders
}
}
- LogDebug($"{nameof(AtLeastOneSocketEstablished)} returning false.");
+ Logger.LogDebug($"{nameof(AtLeastOneSocketEstablished)} returning false.");
return false;
}
@@ -1209,7 +1210,7 @@ namespace MouseWithoutBorders
if (machineCt < 2 && Common.Settings != null && (Common.Settings.GetCurrentPage() is SetupPage1 || Common.Settings.GetCurrentPage() is SetupPage2b))
{
Common.MachineMatrix = new string[Common.MAX_MACHINE] { Common.MachineName.Trim(), desMachine, string.Empty, string.Empty };
- Common.LogDebug("UpdateSetupMachineMatrix: " + string.Join(",", Common.MachineMatrix));
+ Logger.LogDebug("UpdateSetupMachineMatrix: " + string.Join(",", Common.MachineMatrix));
Common.DoSomethingInUIThread(
() =>
@@ -1240,7 +1241,7 @@ namespace MouseWithoutBorders
catch (Exception e)
{
Sk = null;
- Log(e);
+ Logger.Log(e);
}
if (Sk != null)
@@ -1325,7 +1326,7 @@ namespace MouseWithoutBorders
});
}
- LogDebug("GetMyStorageDir: " + st);
+ Logger.LogDebug("GetMyStorageDir: " + st);
// Delete old files.
foreach (FileInfo fi in new DirectoryInfo(st).GetFiles())
@@ -1340,7 +1341,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
if (string.IsNullOrEmpty(st) || !st.Contains(Common.BinaryName))
{
@@ -1358,11 +1359,11 @@ namespace MouseWithoutBorders
try
{
machine_Name = Dns.GetHostName();
- LogDebug("GetHostName = " + machine_Name);
+ Logger.LogDebug("GetHostName = " + machine_Name);
}
catch (Exception e)
{
- Log(e);
+ Logger.Log(e);
if (string.IsNullOrEmpty(machine_Name))
{
@@ -1377,7 +1378,7 @@ namespace MouseWithoutBorders
Common.MachineName = machine_Name.Trim();
- LogDebug($"========== {nameof(GetMachineName)} ended!");
+ Logger.LogDebug($"========== {nameof(GetMachineName)} ended!");
}
private static string GetNetworkName(NetworkInterface networkInterface)
@@ -1405,7 +1406,7 @@ namespace MouseWithoutBorders
}
catch (ObjectDisposedException e)
{
- Log($"{nameof(GetRemoteStringIP)}: The socket could have been disposed by other threads, error: {e.Message}");
+ Logger.Log($"{nameof(GetRemoteStringIP)}: The socket could have been disposed by other threads, error: {e.Message}");
if (throwException)
{
@@ -1416,7 +1417,7 @@ namespace MouseWithoutBorders
}
catch (SocketException e)
{
- Log($"{nameof(GetRemoteStringIP)}: {e.Message}");
+ Logger.Log($"{nameof(GetRemoteStringIP)}: {e.Message}");
if (throwException)
{
@@ -1466,7 +1467,7 @@ namespace MouseWithoutBorders
internal static void MoveMouseToCenter()
{
- LogDebug("+++++ MoveMouseToCenter");
+ Logger.LogDebug("+++++ MoveMouseToCenter");
InputSimulation.MoveMouse(
Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2),
Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2));
@@ -1482,7 +1483,7 @@ namespace MouseWithoutBorders
{
_ = NativeMethods.SetCursorPos(Common.LastPos.X, Common.LastPos.Y);
_ = NativeMethods.GetCursorPos(ref Common.lastPos);
- LogDebug($"+++++ HideMouseCursor, byHideMouseMessage = {byHideMouseMessage}");
+ Logger.LogDebug($"+++++ HideMouseCursor, byHideMouseMessage = {byHideMouseMessage}");
}
CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
@@ -1493,7 +1494,7 @@ namespace MouseWithoutBorders
int length = NativeMethods.GetWindowTextLength(hWnd);
StringBuilder sb = new(length + 1);
int rv = NativeMethods.GetWindowText(hWnd, sb, sb.Capacity);
- LogDebug("GetWindowText returned " + rv.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("GetWindowText returned " + rv.ToString(CultureInfo.CurrentCulture));
return sb.ToString();
}
@@ -1536,14 +1537,14 @@ namespace MouseWithoutBorders
if (read != toRead)
{
- Common.LogDebug("Stream has no more data after reading {0} bytes.", read);
+ Logger.LogDebug("Stream has no more data after reading {0} bytes.", read);
}
}
}
catch (IOException e)
{
string log = $"{nameof(SendOrReceiveARandomDataBlockPerInitialIV)}: Exception {(send ? "writing" : "reading")} to the socket stream: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
if (e.InnerException is not (SocketException or ObjectDisposedException))
{
diff --git a/src/modules/MouseWithoutBorders/App/Class/CustomCursor.cs b/src/modules/MouseWithoutBorders/App/Class/CustomCursor.cs
index d1e56f7f8a..dc90471d4c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/CustomCursor.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/CustomCursor.cs
@@ -16,6 +16,8 @@ using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
+using MouseWithoutBorders.Core;
+
// Disable the warning to preserve original code
#pragma warning disable CA1716
namespace MouseWithoutBorders.Class
@@ -107,12 +109,12 @@ namespace MouseWithoutBorders.Class
}
catch (NullReferenceException)
{
- Common.Log($"{nameof(Common.MouseCursorForm)} has been set to null by another thread.");
+ Logger.Log($"{nameof(Common.MouseCursorForm)} has been set to null by another thread.");
Common.MouseCursorForm = new FrmMouseCursor();
}
catch (ObjectDisposedException)
{
- Common.Log($"{nameof(Common.MouseCursorForm)} has been disposed.");
+ Logger.Log($"{nameof(Common.MouseCursorForm)} has been disposed.");
Common.MouseCursorForm = new FrmMouseCursor();
}
},
@@ -134,11 +136,11 @@ namespace MouseWithoutBorders.Class
}
catch (NullReferenceException)
{
- Common.Log($"{nameof(Common.MouseCursorForm)} has already been set to null by another thread!");
+ Logger.Log($"{nameof(Common.MouseCursorForm)} has already been set to null by another thread!");
}
catch (ObjectDisposedException)
{
- Common.Log($"{nameof(Common.MouseCursorForm)} has already been disposed!");
+ Logger.Log($"{nameof(Common.MouseCursorForm)} has already been disposed!");
}
Common.MouseCursorForm = null;
diff --git a/src/modules/MouseWithoutBorders/App/Class/Extensions.cs b/src/modules/MouseWithoutBorders/App/Class/Extensions.cs
index e199a5797c..0103c3e4e3 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Extensions.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Extensions.cs
@@ -6,7 +6,12 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
+using MouseWithoutBorders.Core;
+
+// Disable the warning to preserve original code
+#pragma warning disable CA1716
namespace MouseWithoutBorders.Class
+#pragma warning restore CA1716
{
internal static class Extensions
{
@@ -39,7 +44,7 @@ namespace MouseWithoutBorders.Class
catch (Win32Exception e)
{
string log = $"The process {processName} (PID={processId}) could not be terminated, error: {e.Message}";
- Common.TelemetryLogTrace(log, SeverityLevel.Error);
+ Logger.TelemetryLogTrace(log, SeverityLevel.Error);
Common.ShowToolTip(log, 5000);
if (!keepTrying)
diff --git a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
index c88ac5a6da..ecaeef77db 100644
--- a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
@@ -23,8 +23,9 @@ using StreamJsonRpc;
#if !MM_HELPER
using MouseWithoutBorders.Class;
-
+using MouseWithoutBorders.Core;
#endif
+
using SystemClipboard = System.Windows.Forms.Clipboard;
namespace MouseWithoutBorders
@@ -127,7 +128,7 @@ namespace MouseWithoutBorders
{
public void SendLog(string log)
{
- Common.LogDebug("FROM HELPER: " + log);
+ Logger.LogDebug("FROM HELPER: " + log);
if (!string.IsNullOrEmpty(log))
{
@@ -143,7 +144,7 @@ namespace MouseWithoutBorders
}
else if (log.StartsWith("Trace:", StringComparison.InvariantCulture))
{
- Common.TelemetryLogTrace(log, SeverityLevel.Information);
+ Logger.TelemetryLogTrace(log, SeverityLevel.Information);
}
}
}
@@ -197,7 +198,7 @@ WellKnownSidType.AuthenticatedUserSid, null);
#if MM_HELPER
_ = e;
#else
- Common.Log(e);
+ Logger.Log(e);
#endif
}
},
@@ -247,7 +248,7 @@ WellKnownSidType.AuthenticatedUserSid, null);
{
Common.IpcChannelCreated = false;
Common.ShowToolTip("Error setting up clipboard sharing, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
- Common.Log(e);
+ Logger.Log(e);
}
}
#else
@@ -263,7 +264,7 @@ WellKnownSidType.AuthenticatedUserSid, null);
}
catch (Exception e)
{
- Logger.LogEvent(e.Message, EventLogEntryType.Error);
+ EventLogger.LogEvent(e.Message, EventLogEntryType.Error);
}
return null;
@@ -272,7 +273,7 @@ WellKnownSidType.AuthenticatedUserSid, null);
}
- internal static class Logger
+ internal static class EventLogger
{
#if MM_HELPER
private const string EventSourceName = "MouseWithoutBordersHelper";
diff --git a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
index 88306a4720..59b5974a80 100644
--- a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
@@ -19,6 +19,7 @@ using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.PowerToys.Settings.UI.Library;
+using MouseWithoutBorders.Core;
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.InputHook.#MouseHookProc(System.Int32,System.Int32,System.IntPtr)", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "MouseWithoutBorders.InputHook.#ProcessKeyEx(System.Int32,System.Int32)", Justification = "Dotnet port with style preservation")]
@@ -117,7 +118,7 @@ namespace MouseWithoutBorders.Class
if (hMouseHook == 0)
{
le = Marshal.GetLastWin32Error();
- Common.Log("Error installing Mouse hook: " + le.ToString(CultureInfo.CurrentCulture));
+ Logger.Log("Error installing Mouse hook: " + le.ToString(CultureInfo.CurrentCulture));
er = true;
Stop();
}
@@ -133,7 +134,7 @@ namespace MouseWithoutBorders.Class
if (hKeyboardHook == 0)
{
le = Marshal.GetLastWin32Error();
- Common.Log("Error installing keyboard hook: " + le.ToString(CultureInfo.CurrentCulture));
+ Logger.Log("Error installing keyboard hook: " + le.ToString(CultureInfo.CurrentCulture));
er = true;
Stop();
}
@@ -166,7 +167,7 @@ namespace MouseWithoutBorders.Class
int errorCode = Marshal.GetLastWin32Error();
// throw new Win32Exception(errorCode);
- Common.Log("Exception uninstalling Mouse hook, error code: " + errorCode.ToString(CultureInfo.CurrentCulture));
+ Logger.Log("Exception uninstalling Mouse hook, error code: " + errorCode.ToString(CultureInfo.CurrentCulture));
}
}
@@ -179,7 +180,7 @@ namespace MouseWithoutBorders.Class
int errorCode = Marshal.GetLastWin32Error();
// throw new Win32Exception(errorCode);
- Common.Log("Exception uninstalling keyboard hook, error code: " + errorCode.ToString(CultureInfo.CurrentCulture));
+ Logger.Log("Exception uninstalling keyboard hook, error code: " + errorCode.ToString(CultureInfo.CurrentCulture));
}
}
}
@@ -234,7 +235,7 @@ namespace MouseWithoutBorders.Class
{
if (wParam == Common.WM_LBUTTONUP && SkipMouseUpCount > 0)
{
- Common.LogDebug($"{nameof(SkipMouseUpCount)}: {SkipMouseUpCount}.");
+ Logger.LogDebug($"{nameof(SkipMouseUpCount)}: {SkipMouseUpCount}.");
SkipMouseUpCount--;
rv = NativeMethods.CallNextHookEx(hMouseHook, nCode, wParam, lParam);
return rv;
@@ -326,7 +327,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
rv = NativeMethods.CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
@@ -455,7 +456,7 @@ namespace MouseWithoutBorders.Class
break;
default:
- Common.LogDebug("X");
+ Logger.LogDebug("X");
return ProcessHotKeys(vkCode, hookCallbackKeybdData);
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
index 5ff39f8adc..bca6e4b28f 100644
--- a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
@@ -17,6 +17,7 @@ using System.ServiceProcess;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library;
+using MouseWithoutBorders.Core;
using Windows.UI.Input.Preview.Injection;
using static MouseWithoutBorders.Class.NativeMethods;
@@ -152,7 +153,7 @@ namespace MouseWithoutBorders.Class
}
log += "*"; // ((Keys)kd.wVk).ToString(CultureInfo.InvariantCulture);
- Common.LogDebug(log);
+ Logger.LogDebug(log);
}
// Md.X, Md.Y is from 0 to 65535
@@ -174,7 +175,7 @@ namespace MouseWithoutBorders.Class
if (md.dwFlags != Common.WM_MOUSEMOVE)
{
- Common.LogDebug($"InputSimulation.SendMouse: x = {md.X}, y = {md.Y}, WheelDelta = {md.WheelDelta}, dwFlags = {md.dwFlags}.");
+ Logger.LogDebug($"InputSimulation.SendMouse: x = {md.X}, y = {md.Y}, WheelDelta = {md.WheelDelta}, dwFlags = {md.dwFlags}.");
}
switch (md.dwFlags)
@@ -242,7 +243,7 @@ namespace MouseWithoutBorders.Class
mouse_input.mi.dx = (int)dx;
mouse_input.mi.dy = (int)dy;
- Common.LogDebug($"InputSimulation.MoveMouseEx: x = {x}, y = {y}.");
+ Logger.LogDebug($"InputSimulation.MoveMouseEx: x = {x}, y = {y}.");
mouse_input.mi.dwFlags |= (int)(NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE);
@@ -264,7 +265,7 @@ namespace MouseWithoutBorders.Class
mouse_input.mi.mouseData = 0;
mouse_input.mi.dwFlags = (int)(NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE);
- Common.LogDebug($"InputSimulation.MoveMouse: x = {x}, y = {y}.");
+ Logger.LogDebug($"InputSimulation.MoveMouse: x = {x}, y = {y}.");
Common.DoSomethingInTheInputSimulationThread(() =>
{
@@ -285,7 +286,7 @@ namespace MouseWithoutBorders.Class
mouse_input.mi.mouseData = 0;
mouse_input.mi.dwFlags = (int)NativeMethods.MOUSEEVENTF.MOVE;
- Common.LogDebug($"InputSimulation.MoveMouseRelative: x = {dx}, y = {dy}.");
+ Logger.LogDebug($"InputSimulation.MoveMouseRelative: x = {dx}, y = {dy}.");
Common.DoSomethingInTheInputSimulationThread(() =>
{
@@ -309,7 +310,7 @@ namespace MouseWithoutBorders.Class
InputHook.SkipMouseUpCount++;
_ = SendInputEx(input);
- Common.LogDebug("MouseUp() called");
+ Logger.LogDebug("MouseUp() called");
});
}
@@ -338,7 +339,7 @@ namespace MouseWithoutBorders.Class
input.mi.dwFlags = (int)NativeMethods.MOUSEEVENTF.LEFTUP;
_ = SendInputEx(input);
- Common.LogDebug("MouseClick() called");
+ Logger.LogDebug("MouseClick() called");
Thread.Sleep(200);
}
finally
@@ -450,7 +451,7 @@ namespace MouseWithoutBorders.Class
eatKey = true;
Common.ReleaseAllKeys();
uint rv = NativeMethods.LockWorkStation();
- Common.LogDebug("LockWorkStation returned " + rv.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("LockWorkStation returned " + rv.ToString(CultureInfo.CurrentCulture));
}
break;
diff --git a/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs b/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs
index 758b41d331..01371bb2ac 100644
--- a/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/NativeMethods.cs
@@ -36,7 +36,10 @@ using System.Text;
[module: SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable", Scope = "member", Target = "MouseWithoutBorders.NativeMethods.#GetAsyncKeyState(System.IntPtr)", MessageId = "0", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable", Scope = "member", Target = "MouseWithoutBorders.NativeMethods.#GetAsyncKeyState(System.IntPtr)", MessageId = "return", Justification = "Dotnet port with style preservation")]
+// Disable the warning to preserve original code
+#pragma warning disable CA1716
namespace MouseWithoutBorders.Class
+#pragma warning restore CA1716
{
internal partial class NativeMethods
{
diff --git a/src/modules/MouseWithoutBorders/App/Class/Program.cs b/src/modules/MouseWithoutBorders/App/Class/Program.cs
index 025c6b9b88..ac33da9ae9 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Program.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Program.cs
@@ -34,6 +34,8 @@ using Microsoft.PowerToys.Telemetry;
using Newtonsoft.Json;
using StreamJsonRpc;
+using Logger = MouseWithoutBorders.Core.Logger;
+
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", Scope = "member", Target = "MouseWithoutBorders.Program.#Main()", MessageId = "System.String.ToLower", Justification = "Dotnet port with style preservation")]
@@ -53,11 +55,13 @@ namespace MouseWithoutBorders.Class
private static void Main()
{
ManagedCommon.Logger.InitializeLogger("\\MouseWithoutBorders\\Logs");
- Common.Log(Application.ProductName + " Started!");
+ Logger.Log(Application.ProductName + " Started!");
+
+ ETWTrace etwTrace = new ETWTrace();
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
{
- Common.Log("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
+ Logger.Log("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
return;
}
@@ -81,9 +85,9 @@ namespace MouseWithoutBorders.Class
}
User = WindowsIdentity.GetCurrent().Name;
- Common.LogDebug("*** Started as " + User);
+ Logger.LogDebug("*** Started as " + User);
- Common.Log(Environment.CommandLine);
+ Logger.Log(Environment.CommandLine);
bool serviceMode = firstArg == ServiceModeArg;
@@ -99,8 +103,8 @@ namespace MouseWithoutBorders.Class
}
catch (Exception ex)
{
- Common.Log("Couldn't start the service. Will try to continue as not a service.");
- Common.Log(ex);
+ Logger.Log("Couldn't start the service. Will try to continue as not a service.");
+ Logger.Log(ex);
ShowServiceModeErrorTooltip = true;
serviceMode = false;
Setting.Values.UseService = false;
@@ -115,13 +119,13 @@ namespace MouseWithoutBorders.Class
}
}
- ShutdownWithPowerToys.WaitForPowerToysRunner();
+ ShutdownWithPowerToys.WaitForPowerToysRunner(etwTrace);
if (firstArg != string.Empty)
{
if (Common.CheckSecondInstance(Common.RunWithNoAdminRight))
{
- Common.Log("*** Second instance, exiting...");
+ Logger.Log("*** Second instance, exiting...");
return;
}
@@ -130,16 +134,16 @@ namespace MouseWithoutBorders.Class
if (firstArg.Equals("winlogon", StringComparison.OrdinalIgnoreCase))
{
// Executed by service, running on logon desktop
- Common.Log("*** Running on " + firstArg + " desktop");
+ Logger.Log("*** Running on " + firstArg + " desktop");
Common.RunOnLogonDesktop = true;
}
else if (args[1].Trim().Equals("default", StringComparison.OrdinalIgnoreCase))
{
- Common.Log("*** Running on " + firstArg + " desktop");
+ Logger.Log("*** Running on " + firstArg + " desktop");
}
else if (args[1].Equals(myDesktop, StringComparison.OrdinalIgnoreCase))
{
- Common.Log("*** Running on " + myDesktop);
+ Logger.Log("*** Running on " + myDesktop);
if (myDesktop.Equals("Screen-saver", StringComparison.OrdinalIgnoreCase))
{
Common.RunOnScrSaverDesktop = true;
@@ -151,7 +155,7 @@ namespace MouseWithoutBorders.Class
{
if (Common.CheckSecondInstance(true))
{
- Common.Log("*** Second instance, exiting...");
+ Logger.Log("*** Second instance, exiting...");
return;
}
}
@@ -165,10 +169,10 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
- Common.Log(Environment.OSVersion.ToString());
+ Logger.Log(Environment.OSVersion.ToString());
// Environment.OSVersion is unreliable from 6.2 and up, so just forcefully call the APIs and log the exception unsupported by Windows:
int setProcessDpiAwarenessResult = -1;
@@ -176,31 +180,31 @@ namespace MouseWithoutBorders.Class
try
{
setProcessDpiAwarenessResult = NativeMethods.SetProcessDpiAwareness(2);
- Common.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDpiAwareness: {0}.", setProcessDpiAwarenessResult));
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDpiAwareness: {0}.", setProcessDpiAwarenessResult));
}
catch (DllNotFoundException)
{
- Common.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
+ Logger.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
}
catch (EntryPointNotFoundException)
{
- Common.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
+ Logger.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
try
{
if (setProcessDpiAwarenessResult != 0)
{
- Common.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDPIAware: {0}.", NativeMethods.SetProcessDPIAware()));
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDPIAware: {0}.", NativeMethods.SetProcessDPIAware()));
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
System.Threading.Thread mainUIThread = Thread.CurrentThread;
@@ -223,10 +227,12 @@ namespace MouseWithoutBorders.Class
var formScreen = new FrmScreen();
Application.Run(formScreen);
+
+ etwTrace?.Dispose();
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -397,14 +403,14 @@ namespace MouseWithoutBorders.Class
{
if (pp.Id != me.Id)
{
- Common.Log(string.Format(CultureInfo.InvariantCulture, "Killing process {0}.", pp.Id));
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process {0}.", pp.Id));
pp.KillProcess();
}
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
Common.StartMouseWithoutBordersService();
diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
index 6ce32bbc2f..a2eb300b0c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
@@ -29,6 +29,7 @@ using Microsoft.PowerToys.Settings.UI.Library.Utilities;
// 2023- Included in PowerToys.
//
using Microsoft.Win32;
+using MouseWithoutBorders.Core;
using Settings.UI.Library.Attributes;
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadIntSetting(System.String,System.Int32)", Justification = "Dotnet port with style preservation")]
@@ -133,7 +134,7 @@ namespace MouseWithoutBorders.Class
}
catch (IOException ex)
{
- Logger.LogEvent($"Failed to read settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
+ EventLogger.LogEvent($"Failed to read settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
}
PauseInstantSaving = false;
@@ -168,7 +169,7 @@ namespace MouseWithoutBorders.Class
}
catch (IOException ex)
{
- Logger.LogEvent($"Failed to write settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
+ EventLogger.LogEvent($"Failed to write settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
}
if (saved)
@@ -198,7 +199,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception ex)
{
- Logger.LogEvent($"Failed to update settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
+ EventLogger.LogEvent($"Failed to update settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
}
});
@@ -442,7 +443,7 @@ namespace MouseWithoutBorders.Class
{
if (_properties.SecurityKey.Value.Length != 0)
{
- Common.LogDebug("GETSECKEY: Key was already loaded/set: " + _properties.SecurityKey.Value);
+ Logger.LogDebug("GETSECKEY: Key was already loaded/set: " + _properties.SecurityKey.Value);
return _properties.SecurityKey.Value;
}
else
diff --git a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
index 57600cde95..a6cf02e348 100644
--- a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
@@ -17,6 +17,7 @@ using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
+using MouseWithoutBorders.Core;
//
// Socket code.
@@ -174,12 +175,12 @@ namespace MouseWithoutBorders.Class
internal SocketStuff(int port, bool byUser)
{
- Common.LogDebug("SocketStuff started.");
+ Logger.LogDebug("SocketStuff started.");
bASE_PORT = port;
Common.Ran = new Random();
- Common.LogDebug("Validating session...");
+ Logger.LogDebug("Validating session...");
if (Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
@@ -198,12 +199,12 @@ namespace MouseWithoutBorders.Class
}
Common.MMSleep(1);
- Common.Log("Not physical console session.");
+ Logger.Log("Not physical console session.");
throw new NotPhysicalConsoleException("Not physical console session.");
}
- Common.LogDebug("Creating socket list and mutex...");
+ Logger.LogDebug("Creating socket list and mutex...");
try
{
@@ -235,7 +236,7 @@ namespace MouseWithoutBorders.Class
}
catch (AbandonedMutexException e)
{
- Common.TelemetryLogTrace($"{nameof(SocketStuff)}: {e.Message}", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"{nameof(SocketStuff)}: {e.Message}", SeverityLevel.Warning);
}
Common.GetScreenConfig();
@@ -280,7 +281,7 @@ namespace MouseWithoutBorders.Class
Common.GetMachineName(); // IPs might have been changed
Common.UpdateMachineTimeAndID();
- Common.LogDebug("Creating sockets...");
+ Logger.LogDebug("Creating sockets...");
openSocketErr = CreateSocket();
@@ -303,7 +304,7 @@ namespace MouseWithoutBorders.Class
// It is reasonable to give a try on restarting MwB processes in other sessions.
if (restartCount++ < 5 && Common.IsMyDesktopActive() && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
- Common.TelemetryLogTrace("Restarting the service dues to WSAEADDRINUSE.", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace("Restarting the service dues to WSAEADDRINUSE.", SeverityLevel.Warning);
Program.StartService();
Common.PleaseReopenSocket = Common.REOPEN_WHEN_WSAECONNRESET;
}
@@ -367,11 +368,11 @@ namespace MouseWithoutBorders.Class
"Closing sockets",
() =>
{
- Common.LogDebug($"Closing socket [{skMessageServer?.Name}].");
+ Logger.LogDebug($"Closing socket [{skMessageServer?.Name}].");
skMessageServer?.Close(); // The original ones, not the socket instances produced by the accept() method.
skMessageServer = null;
- Common.LogDebug($"Closing socket [{skClipboardServer?.Name}].");
+ Logger.LogDebug($"Closing socket [{skClipboardServer?.Name}].");
skClipboardServer?.Close();
skClipboardServer = null;
try
@@ -383,7 +384,7 @@ namespace MouseWithoutBorders.Class
if (TcpSockets != null)
{
- Common.LogDebug("********** Closing Sockets: " + TcpSockets.Count.ToString(CultureInfo.InvariantCulture));
+ Logger.LogDebug("********** Closing Sockets: " + TcpSockets.Count.ToString(CultureInfo.InvariantCulture));
List notClosedSockets = new();
@@ -412,16 +413,16 @@ namespace MouseWithoutBorders.Class
catch (SocketException e)
{
string log = $"Socket.Close error: {e.GetType()}/{e.Message}. This is expected when the socket is already closed by remote host.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (ObjectDisposedException e)
{
string log = $"Socket.Close error: {e.GetType()}/{e.Message}. This is expected when the socket is already disposed.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
// If there was an error closing the socket:
@@ -435,12 +436,12 @@ namespace MouseWithoutBorders.Class
TcpSockets = notClosedSockets;
}
- Common.LogDebug("********** Sockets Closed: " + c.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("********** Sockets Closed: " + c.ToString(CultureInfo.CurrentCulture));
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
},
TimeSpan.FromSeconds(3),
@@ -448,7 +449,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
finally
{
@@ -463,7 +464,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
}
@@ -477,16 +478,16 @@ namespace MouseWithoutBorders.Class
}
catch (SocketException e)
{
- Common.Log(e);
+ Logger.Log(e);
return e;
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
return e;
}
- Common.LogDebug("==================================================");
+ Logger.LogDebug("==================================================");
return null;
}
@@ -497,7 +498,7 @@ namespace MouseWithoutBorders.Class
if (tcp.BackingSocket == null || !tcp.BackingSocket.Connected || encryptedStream == null)
{
string log = $"{nameof(TcpSendData)}: The socket is no longer connected, it could have been closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
throw new ExpectedSocketException(log);
}
@@ -516,7 +517,7 @@ namespace MouseWithoutBorders.Class
catch (IOException e)
{
string log = $"{nameof(TcpSendData)}: Exception writing to the socket: {tcp.MachineName}: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
throw e.InnerException is SocketException se ? new ExpectedSocketException(se) : new ExpectedSocketException(log);
}
@@ -533,7 +534,7 @@ namespace MouseWithoutBorders.Class
if (magic != (Common.MagicNumber & 0xFFFF0000))
{
- Common.Log("Magic number invalid!");
+ Logger.Log("Magic number invalid!");
buf[0] = (byte)PackageType.Invalid;
}
@@ -544,7 +545,7 @@ namespace MouseWithoutBorders.Class
if (buf[1] != checksum)
{
- Common.Log("Checksum invalid!");
+ Logger.Log("Checksum invalid!");
buf[0] = (byte)PackageType.Invalid;
}
@@ -559,7 +560,7 @@ namespace MouseWithoutBorders.Class
if (tcp.BackingSocket == null || !tcp.BackingSocket.Connected || decryptedStream == null)
{
string log = $"{nameof(TcpReceiveData)}: The socket is no longer connected, it could have been closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
throw new ExpectedSocketException(log);
}
@@ -597,7 +598,7 @@ namespace MouseWithoutBorders.Class
catch (IOException e)
{
string log = $"{nameof(TcpReceiveData)}: Exception reading from the socket: {tcp.MachineName}: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
throw e.InnerException is SocketException se ? new ExpectedSocketException(se) : new ExpectedSocketException(log);
}
@@ -668,7 +669,7 @@ namespace MouseWithoutBorders.Class
int rv = TcpSendData(tcp, dataAsBytes);
if (rv < dataAsBytes.Length)
{
- Common.Log("TcpSend error! Length of sent data is unexpected.");
+ Logger.Log("TcpSend error! Length of sent data is unexpected.");
UpdateTcpSockets(tcp, SocketStatus.SendError);
throw new SocketException((int)SocketStatus.SendError);
}
@@ -683,7 +684,7 @@ namespace MouseWithoutBorders.Class
TcpListener server = param as TcpListener;
do
{
- Common.LogDebug("TCPServerThread: Waiting for request...");
+ Logger.LogDebug("TCPServerThread: Waiting for request...");
Socket s = server.AcceptSocket();
_ = Task.Run(() =>
@@ -694,7 +695,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
});
}
@@ -703,22 +704,22 @@ namespace MouseWithoutBorders.Class
catch (InvalidOperationException e)
{
string log = $"TCPServerThread.AcceptSocket: The server socket could have been closed. {e.Message}";
- Common.Log(log);
+ Logger.Log(log);
}
catch (SocketException e)
{
if (e.ErrorCode == (int)SocketError.Interrupted)
{
- Common.Log("TCPServerThread.AcceptSocket: A blocking socket call was canceled.");
+ Logger.Log("TCPServerThread.AcceptSocket: A blocking socket call was canceled.");
}
else
{
- Common.Log(e);
+ Logger.Log(e);
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -734,7 +735,7 @@ namespace MouseWithoutBorders.Class
}
catch (SocketException e)
{
- Common.Log($"{nameof(GetMachineNameFromSocket)}: {e.Message}");
+ Logger.Log($"{nameof(GetMachineNameFromSocket)}: {e.Message}");
return stringIP;
}
@@ -745,7 +746,7 @@ namespace MouseWithoutBorders.Class
if (dotPos > 0)
{
- Common.LogDebug("Removing domain part from the full machine name: {0}.", name);
+ Logger.LogDebug("Removing domain part from the full machine name: {0}.", name);
name = name[..dotPos];
}
}
@@ -756,7 +757,7 @@ namespace MouseWithoutBorders.Class
private void AddSocket(Socket s)
{
string machineName = GetMachineNameFromSocket(s);
- Common.Log($"New connection from client: [{machineName}].");
+ Logger.Log($"New connection from client: [{machineName}].");
TcpSk tcp = AddTcpSocket(false, s, SocketStatus.Connecting, machineName);
StartNewTcpServer(tcp, machineName);
}
@@ -772,7 +773,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -789,13 +790,13 @@ namespace MouseWithoutBorders.Class
return;
}
- Common.LogDebug("!!!!! UpdateTCPClients !!!!!");
+ Logger.LogDebug("!!!!! UpdateTCPClients !!!!!");
try
{
if (Common.MachineMatrix != null)
{
- Common.LogDebug("MachineMatrix = " + string.Join(", ", Common.MachineMatrix));
+ Logger.LogDebug("MachineMatrix = " + string.Join(", ", Common.MachineMatrix));
foreach (string st in Common.MachineMatrix)
{
@@ -809,7 +810,7 @@ namespace MouseWithoutBorders.Class
if (found)
{
- Common.LogDebug(machineName + " is already connected! ^^^^^^^^^^^^^^^^^^^^^");
+ Logger.LogDebug(machineName + " is already connected! ^^^^^^^^^^^^^^^^^^^^^");
continue;
}
@@ -820,7 +821,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -883,7 +884,7 @@ namespace MouseWithoutBorders.Class
Socket dummySocket = new(AddressFamily.Unspecified, SocketType.Stream, ProtocolType.Tcp);
TcpSk dummyTcp = AddTcpSocket(true, dummySocket, SocketStatus.Resolving, machineName);
- Common.LogDebug("Connecting to: " + machineName);
+ Logger.LogDebug("Connecting to: " + machineName);
if (!string.IsNullOrEmpty(Setting.Values.Name2IP))
{
@@ -911,7 +912,7 @@ namespace MouseWithoutBorders.Class
{
useName2IP = true;
- Common.LogDebug("Using both user-defined Name-to-IP mappings and DNS result for " + machineName);
+ Logger.LogDebug("Using both user-defined Name-to-IP mappings and DNS result for " + machineName);
Common.ShowToolTip("Using both user-defined Name-to-IP mappings and DNS result for " + machineName, 3000, ToolTipIcon.Info, false);
@@ -941,7 +942,7 @@ namespace MouseWithoutBorders.Class
Common.ShowToolTip(e.Message + ": " + machineName, 10000, ToolTipIcon.Warning, Setting.Values.ShowClipNetStatus);
- Common.Log($"{nameof(StartNewTcpClient)}.{nameof(Dns.GetHostEntry)}: {e.Message}");
+ Logger.Log($"{nameof(StartNewTcpClient)}.{nameof(Dns.GetHostEntry)}: {e.Message}");
}
UpdateTcpSockets(dummyTcp, SocketStatus.NA);
@@ -967,7 +968,7 @@ namespace MouseWithoutBorders.Class
}
}
- Common.LogDebug(machineName + ipLog);
+ Logger.LogDebug(machineName + ipLog);
}
if (validAddresses.Count > 0)
@@ -983,7 +984,7 @@ namespace MouseWithoutBorders.Class
{
if (IsBadIP(machineName, ip))
{
- Common.Log($"Skip bad IP address: {ip}");
+ Logger.Log($"Skip bad IP address: {ip}");
continue;
}
@@ -998,18 +999,18 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.Log($"DNS information of machine not matched: {machineName} => {ip} => {hn}.");
+ Logger.Log($"DNS information of machine not matched: {machineName} => {ip} => {hn}.");
AddBadIP(machineName, ip);
}
}
catch (SocketException se)
{
- Common.Log($"{nameof(StartNewTcpClient)}: DNS information of machine not matched: {machineName} => {ip} => {se.Message}.");
+ Logger.Log($"{nameof(StartNewTcpClient)}: DNS information of machine not matched: {machineName} => {ip} => {se.Message}.");
AddBadIP(machineName, ip);
}
catch (ArgumentException ae)
{
- Common.Log($"{nameof(StartNewTcpClient)}: DNS information of machine not matched: {machineName} => {ip} => {ae.Message}.");
+ Logger.Log($"{nameof(StartNewTcpClient)}: DNS information of machine not matched: {machineName} => {ip} => {ae.Message}.");
AddBadIP(machineName, ip);
}
}
@@ -1030,7 +1031,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.Log("Cannot resolve IPv4 Addresses of machine: " + machineName);
+ Logger.Log("Cannot resolve IPv4 Addresses of machine: " + machineName);
if (!useName2IP)
{
@@ -1058,7 +1059,7 @@ namespace MouseWithoutBorders.Class
if (!remoteIPv4Addresses.Any())
{
- Common.Log($"No IPv4 resolved from the remote machine: {machineName}.");
+ Logger.Log($"No IPv4 resolved from the remote machine: {machineName}.");
return true;
}
@@ -1066,7 +1067,7 @@ namespace MouseWithoutBorders.Class
if (localIPv4Addresses.Count == 0)
{
- Common.Log($"No IPv4 resolved from the local machine: {Common.MachineName}");
+ Logger.Log($"No IPv4 resolved from the local machine: {Common.MachineName}");
return true;
}
@@ -1085,7 +1086,7 @@ namespace MouseWithoutBorders.Class
}
}
- Common.Log($"Skip machine not in the same network: {machineName}.");
+ Logger.Log($"Skip machine not in the same network: {machineName}.");
return false;
}
@@ -1105,7 +1106,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
return Enumerable.Empty();
}
}
@@ -1123,13 +1124,13 @@ namespace MouseWithoutBorders.Class
if (Common.IsConnectedByAClientSocketTo(machineName))
{
- Common.LogDebug(machineName + " is already connected by another client socket.");
+ Logger.LogDebug(machineName + " is already connected by another client socket.");
return;
}
if (Common.IsConnectingByAClientSocketTo(machineName, ip))
{
- Common.LogDebug($"{machineName}:{ip} is already being connected by another client socket.");
+ Logger.LogDebug($"{machineName}:{ip} is already being connected by another client socket.");
return;
}
@@ -1138,7 +1139,7 @@ namespace MouseWithoutBorders.Class
// Update the other server socket's machine name based on this corresponding client socket.
UpdateTcpSockets(tcp, SocketStatus.Connecting);
- Common.LogDebug(string.Format(CultureInfo.CurrentCulture, "=====> Connecting to: {0}:{1}", machineName, ip.ToString()));
+ Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "=====> Connecting to: {0}:{1}", machineName, ip.ToString()));
long timeoutLeft;
@@ -1151,7 +1152,7 @@ namespace MouseWithoutBorders.Class
catch (ObjectDisposedException)
{
// When user reconnects.
- Common.LogDebug($"tcpClient.Connect: The socket has already been disposed: {machineName}:{ip}");
+ Logger.LogDebug($"tcpClient.Connect: The socket has already been disposed: {machineName}:{ip}");
return;
}
catch (SocketException e)
@@ -1160,13 +1161,13 @@ namespace MouseWithoutBorders.Class
if (timeoutLeft > 0)
{
- Common.LogDebug($"tcpClient.Connect: {timeoutLeft}: {e.Message}");
+ Logger.LogDebug($"tcpClient.Connect: {timeoutLeft}: {e.Message}");
Thread.Sleep(1000);
continue;
}
else
{
- Common.Log($"tcpClient.Connect: Unable to connect after a timeout: {machineName}:{ip} : {e.Message}");
+ Logger.Log($"tcpClient.Connect: Unable to connect after a timeout: {machineName}:{ip} : {e.Message}");
string message = $"Connection timed out: {machineName}:{ip}";
@@ -1181,14 +1182,14 @@ namespace MouseWithoutBorders.Class
}
while (true);
- Common.LogDebug($"=====> Connected: {tcpClient.Client.LocalEndPoint} => {machineName}: {ip}");
+ Logger.LogDebug($"=====> Connected: {tcpClient.Client.LocalEndPoint} => {machineName}: {ip}");
// Sending/Receiving packages
MainTCPRoutine(tcp, machineName, true);
}
catch (ObjectDisposedException e)
{
- Common.Log($"{nameof(StartNewTcpClientThread)}: The socket could have been closed/disposed due to machine switch: {e.Message}");
+ Logger.Log($"{nameof(StartNewTcpClientThread)}: The socket could have been closed/disposed due to machine switch: {e.Message}");
}
catch (SocketException e)
{
@@ -1201,12 +1202,12 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.TelemetryLogTrace($"{nameof(StartNewTcpClientThread)}: Error: {e.Message} on the IP Address: {localIP}", SeverityLevel.Error);
+ Logger.TelemetryLogTrace($"{nameof(StartNewTcpClientThread)}: Error: {e.Message} on the IP Address: {localIP}", SeverityLevel.Error);
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -1230,7 +1231,7 @@ namespace MouseWithoutBorders.Class
if (e is ExpectedSocketException se && se.ShouldReconnect)
{
Common.PleaseReopenSocket = Common.REOPEN_WHEN_WSAECONNRESET;
- Common.Log($"MainTCPRoutine: {nameof(FlagReopenSocketIfNeeded)}");
+ Logger.Log($"MainTCPRoutine: {nameof(FlagReopenSocketIfNeeded)}");
}
}
@@ -1254,7 +1255,7 @@ namespace MouseWithoutBorders.Class
if (currentSocket == null)
{
- Common.LogDebug($"{nameof(MainTCPRoutine)}: The socket could have been closed/disposed by other threads.");
+ Logger.LogDebug($"{nameof(MainTCPRoutine)}: The socket could have been closed/disposed by other threads.");
return;
}
@@ -1283,21 +1284,21 @@ namespace MouseWithoutBorders.Class
strIP = Common.GetRemoteStringIP(currentSocket, true);
remoteMachine = string.IsNullOrEmpty(machineName) ? GetMachineNameFromSocket(currentSocket) : machineName;
- Common.LogDebug($"MainTCPRoutine: Remote machineName/IP = {remoteMachine}/{strIP}");
+ Logger.LogDebug($"MainTCPRoutine: Remote machineName/IP = {remoteMachine}/{strIP}");
}
catch (ObjectDisposedException e)
{
Common.PleaseReopenSocket = Common.REOPEN_WHEN_WSAECONNRESET;
UpdateTcpSockets(currentTcp, SocketStatus.ForceClosed);
currentSocket.Close();
- Common.Log($"{nameof(MainTCPRoutine)}: The socket could have been closed/disposed by other threads: {e.Message}");
+ Logger.Log($"{nameof(MainTCPRoutine)}: The socket could have been closed/disposed by other threads: {e.Message}");
}
catch (Exception e)
{
UpdateTcpSockets(currentTcp, SocketStatus.ForceClosed);
FlagReopenSocketIfNeeded(e);
currentSocket.Close();
- Common.Log(e);
+ Logger.Log(e);
}
int errCount = 0;
@@ -1314,7 +1315,7 @@ namespace MouseWithoutBorders.Class
errCount++;
string log = $"{nameof(MainTCPRoutine)}.TcpReceive error, invalid package from {remoteMachine}: {receivedCount}";
- Common.Log(log);
+ Logger.Log(log);
if (receivedCount > 0)
{
@@ -1369,7 +1370,7 @@ namespace MouseWithoutBorders.Class
if (++packageCount >= 10)
{
// Common.ShowToolTip("Invalid Security Key from " + remoteMachine, 5000);
- Common.Log("More than 10 invalid packages received!");
+ Logger.Log("More than 10 invalid packages received!");
package.Type = PackageType.Invalid;
@@ -1393,7 +1394,7 @@ namespace MouseWithoutBorders.Class
if (!remoteMachine.Equals(claimedMachineName, StringComparison.Ordinal))
{
- Common.LogDebug($"DNS.RemoteMachineName({remoteMachine}) <> Claimed.MachineName({claimedMachineName}), using the claimed machine name.");
+ Logger.LogDebug($"DNS.RemoteMachineName({remoteMachine}) <> Claimed.MachineName({claimedMachineName}), using the claimed machine name.");
remoteMachine = claimedMachineName;
currentTcp.MachineName = remoteMachine;
}
@@ -1401,7 +1402,7 @@ namespace MouseWithoutBorders.Class
// Double check to avoid a redundant client socket.
if (isClient && Common.IsConnectedByAClientSocketTo(remoteMachine))
{
- Common.LogDebug("=====> Duplicate connected client socket for: " + remoteMachine + ":" + strIP + " is being removed.");
+ Logger.LogDebug("=====> Duplicate connected client socket for: " + remoteMachine + ":" + strIP + " is being removed.");
UpdateTcpSockets(currentTcp, SocketStatus.ForceClosed);
currentSocket.Close();
return;
@@ -1409,7 +1410,7 @@ namespace MouseWithoutBorders.Class
if (remoteMachine.Equals(Common.MachineName, StringComparison.OrdinalIgnoreCase))
{
- Common.LogDebug("Connected to/from local socket: " + strIP + (isClient ? "-Client" : "-Server"));
+ Logger.LogDebug("Connected to/from local socket: " + strIP + (isClient ? "-Client" : "-Server"));
UpdateTcpSockets(currentTcp, SocketStatus.NA);
Common.MMSleep(1);
currentSocket.Close();
@@ -1421,7 +1422,7 @@ namespace MouseWithoutBorders.Class
currentTcp.MachineId = (uint)remoteID;
currentTcp.Status = SocketStatus.Connected;
UpdateTcpSockets(currentTcp, SocketStatus.Connected);
- Common.LogDebug("))))))))))))))) Machine got trusted: " + remoteMachine + ":" + strIP + ", Is client: " + isClient);
+ Logger.LogDebug("))))))))))))))) Machine got trusted: " + remoteMachine + ":" + strIP + ", Is client: " + isClient);
if (Math.Abs(Common.GetTick() - Common.LastReconnectByHotKeyTime) < 5000)
{
@@ -1432,11 +1433,11 @@ namespace MouseWithoutBorders.Class
if (Common.MachinePool.TryFindMachineByName(remoteMachine, out MachineInf machineInfo))
{
- Common.LogDebug("Machine updated: " + remoteMachine + "/" + remoteID.ToString());
+ Logger.LogDebug("Machine updated: " + remoteMachine + "/" + remoteID.ToString());
if (machineInfo.Name.Equals(Common.DesMachineName, StringComparison.OrdinalIgnoreCase))
{
- Common.LogDebug("Des ID updated: " + Common.DesMachineID.ToString() +
+ Logger.LogDebug("Des ID updated: " + Common.DesMachineID.ToString() +
"/" + remoteID.ToString());
Common.NewDesMachineID = Common.DesMachineID = remoteID;
}
@@ -1446,7 +1447,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.LogDebug("New machine connected: {0}.", remoteMachine);
+ Logger.LogDebug("New machine connected: {0}.", remoteMachine);
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
@@ -1461,7 +1462,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.LogDebug("Invalid ACK from " + remoteMachine);
+ Logger.LogDebug("Invalid ACK from " + remoteMachine);
UpdateTcpSockets(currentTcp, SocketStatus.InvalidKey);
string remoteEP = currentSocket.RemoteEndPoint.ToString();
@@ -1500,7 +1501,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.Log(string.Format(
+ Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"Unexpected package, size = {0}, type = {1}",
receivedCount,
@@ -1514,12 +1515,12 @@ namespace MouseWithoutBorders.Class
if (lastRemoteMachineID != (long)remoteID)
{
_ = Interlocked.Exchange(ref lastRemoteMachineID, (long)remoteID);
- Common.LogDebug($"MainTCPRoutine: Remote machine = {strIP}/{lastRemoteMachineID}");
+ Logger.LogDebug($"MainTCPRoutine: Remote machine = {strIP}/{lastRemoteMachineID}");
}
if (package.Type == PackageType.HandshakeAck)
{
- Common.LogDebug("Skipping the rest of the Handshake packages.");
+ Logger.LogDebug("Skipping the rest of the Handshake packages.");
}
else
{
@@ -1533,7 +1534,7 @@ namespace MouseWithoutBorders.Class
UpdateTcpSockets(currentTcp, SocketStatus.Error);
FlagReopenSocketIfNeeded(e);
currentSocket.Close();
- Common.Log(e);
+ Logger.Log(e);
break;
}
}
@@ -1550,7 +1551,7 @@ namespace MouseWithoutBorders.Class
do
{
- Common.LogDebug("SendClipboardData: Waiting for request...");
+ Logger.LogDebug("SendClipboardData: Waiting for request...");
Socket s = null;
try
@@ -1559,25 +1560,25 @@ namespace MouseWithoutBorders.Class
}
catch (InvalidOperationException e)
{
- Common.Log($"The clipboard socket could have been closed. {e.Message}");
+ Logger.Log($"The clipboard socket could have been closed. {e.Message}");
break;
}
catch (SocketException e)
{
if (e.ErrorCode == (int)SocketError.Interrupted)
{
- Common.Log("server.AcceptSocket: A blocking socket call was canceled.");
+ Logger.Log("server.AcceptSocket: A blocking socket call was canceled.");
continue;
}
else
{
- Common.Log(e);
+ Logger.Log(e);
break;
}
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
break;
}
@@ -1595,7 +1596,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
}
@@ -1607,7 +1608,7 @@ namespace MouseWithoutBorders.Class
try
{
string remoteEndPoint = s.RemoteEndPoint.ToString();
- Common.LogDebug("SendClipboardData: Request accepted: " + s.LocalEndPoint.ToString() + "/" + remoteEndPoint);
+ Logger.LogDebug("SendClipboardData: Request accepted: " + s.LocalEndPoint.ToString() + "/" + remoteEndPoint);
Common.IsDropping = false;
Common.IsDragging = false;
Common.DragMachine = (ID)1;
@@ -1623,7 +1624,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.LogDebug($"{nameof(SendOrReceiveClipboardData)}: Clipboard connection accepted: " + remoteEndPoint);
+ Logger.LogDebug($"{nameof(SendOrReceiveClipboardData)}: Clipboard connection accepted: " + remoteEndPoint);
Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE] { Common.ICON_SMALL_CLIPBOARD, -1, -1, -1 });
}
@@ -1638,7 +1639,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -1699,17 +1700,17 @@ namespace MouseWithoutBorders.Class
catch (IOException e)
{
string log = $"{nameof(SendClipboardData)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
catch (SocketException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the connection is closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (ObjectDisposedException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the socket is disposed by a machine switch for ex..";
- Common.Log(log);
+ Logger.Log(log);
}
}
else if (!Common.IsClipboardDataImage && Common.LastClipboardData != null)
@@ -1725,7 +1726,7 @@ namespace MouseWithoutBorders.Class
{
ecStream.Write(header, 0, header.Length);
_ = SendData(s, ecStream, data);
- Common.LogDebug("Text sent: " + data.Length.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("Text sent: " + data.Length.ToString(CultureInfo.CurrentCulture));
}
s.Close(CLOSE_TIMEOUT);
@@ -1733,17 +1734,17 @@ namespace MouseWithoutBorders.Class
catch (IOException e)
{
string log = $"{nameof(SendClipboardData)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
catch (SocketException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the connection is closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (ObjectDisposedException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the socket is disposed by a machine switch for ex..";
- Common.Log(log);
+ Logger.Log(log);
}
}
else if (Common.LastClipboardData != null && Common.LastClipboardData.Length > 0)
@@ -1756,28 +1757,28 @@ namespace MouseWithoutBorders.Class
{
ecStream.Write(header, 0, header.Length);
_ = SendData(s, ecStream, data);
- Common.LogDebug("Image sent: " + data.Length.ToString(CultureInfo.CurrentCulture));
+ Logger.LogDebug("Image sent: " + data.Length.ToString(CultureInfo.CurrentCulture));
s.Close(CLOSE_TIMEOUT);
}
catch (IOException e)
{
string log = $"{nameof(SendClipboardData)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
catch (SocketException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the connection is closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (ObjectDisposedException e)
{
string log = $"{nameof(SendClipboardData)}: {e.GetType()}/{e.Message}. This is expected when the socket is disposed by a machine switch for ex..";
- Common.Log(log);
+ Logger.Log(log);
}
}
else
{
- Common.Log("No data available in clipboard or LastDragDropFile!");
+ Logger.Log("No data available in clipboard or LastDragDropFile!");
s.Close();
}
}
@@ -1809,7 +1810,7 @@ namespace MouseWithoutBorders.Class
ecStream.Flush();
- Common.LogDebug("File sent: " + fileName);
+ Logger.LogDebug("File sent: " + fileName);
}
return true;
@@ -1819,11 +1820,11 @@ namespace MouseWithoutBorders.Class
if (e is IOException)
{
string log = $"{nameof(SendFileEx)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
else
{
- Common.Log(e);
+ Logger.Log(e);
}
Common.ShowToolTip(e.Message, 1000, ToolTipIcon.Warning, Setting.Values.ShowClipNetStatus);
@@ -1879,7 +1880,7 @@ namespace MouseWithoutBorders.Class
}
ecStream.Flush();
- Common.LogDebug("Data sent: " + data.Length.ToString(CultureInfo.InvariantCulture));
+ Logger.LogDebug("Data sent: " + data.Length.ToString(CultureInfo.InvariantCulture));
r = true;
}
catch (Exception e)
@@ -1887,11 +1888,11 @@ namespace MouseWithoutBorders.Class
if (e is IOException)
{
string log = $"{nameof(SendData)}: Exception accessing the socket: {e.InnerException?.GetType()}/{e.Message}. (This is expected when the remote machine closes the connection during desktop switch or reconnection.)";
- Common.Log(log);
+ Logger.Log(log);
}
else
{
- Common.Log(e);
+ Logger.Log(e);
}
Common.ShowToolTip(e.Message, 1000, ToolTipIcon.Warning, Setting.Values.ShowClipNetStatus);
@@ -1960,7 +1961,7 @@ namespace MouseWithoutBorders.Class
Common.UpdateMachineTimeAndID();
Common.PleaseReopenSocket = Common.REOPEN_WHEN_HOTKEY;
- Common.TelemetryLogTrace("MachineID conflict.", SeverityLevel.Information);
+ Logger.TelemetryLogTrace("MachineID conflict.", SeverityLevel.Information);
}
else
{
@@ -1971,7 +1972,7 @@ namespace MouseWithoutBorders.Class
foreach (TcpSk t in tobeRemovedSockets)
{
t.Status = SocketStatus.ForceClosed;
- Common.LogDebug($"Closing duplicated socket {t.MachineName}: {t.Address}");
+ Logger.LogDebug($"Closing duplicated socket {t.MachineName}: {t.Address}");
}
}
@@ -2001,12 +2002,12 @@ namespace MouseWithoutBorders.Class
catch (SocketException e)
{
string log = $"{nameof(UpdateTcpSockets)}: {e.GetType()}/{e.Message}. This is expected when the connection is closed by the remote host.";
- Common.Log(log);
+ Logger.Log(log);
}
catch (ObjectDisposedException e)
{
string log = $"{nameof(UpdateTcpSockets)}: {e.GetType()}/{e.Message}. This is expected when the socket is disposed by a machine switch for ex..";
- Common.Log(log);
+ Logger.Log(log);
}
}
}
@@ -2048,7 +2049,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.Log("UpdateTcpSockets.Exception: Socket not found!");
+ Logger.Log("UpdateTcpSockets.Exception: Socket not found!");
}
foreach (TcpSk t in toBeRemoved)
@@ -2060,7 +2061,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
index f7ea7ba094..ffff1ce76b 100644
--- a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
@@ -11,6 +11,8 @@ using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
+using MouseWithoutBorders.Core;
+
//
// TCP Server implementation.
//
@@ -33,7 +35,7 @@ namespace MouseWithoutBorders.Class
internal TcpServer(int port, ParameterizedThreadStart job)
{
- Common.Log($"TCP listening on port: {port}");
+ Logger.Log($"TCP listening on port: {port}");
Name = port.ToString(CultureInfo.CurrentCulture);
server = TcpListener.Create(port);
StartServer(job);
@@ -79,7 +81,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.TelemetryLogTrace($"Error listening on: {server.LocalEndpoint}: {e.ErrorCode}/{e.Message}", SeverityLevel.Error);
+ Logger.TelemetryLogTrace($"Error listening on: {server.LocalEndpoint}: {e.ErrorCode}/{e.Message}", SeverityLevel.Error);
throw;
}
}
@@ -99,7 +101,7 @@ namespace MouseWithoutBorders.Class
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Core/Logger.cs b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
new file mode 100644
index 0000000000..8d4c42e373
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
@@ -0,0 +1,447 @@
+// 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.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+
+//
+// Logging.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Exceptions;
+
+namespace MouseWithoutBorders.Core;
+
+internal static class Logger
+{
+ internal static readonly string[] AllLogs = new string[MAX_LOG];
+ private static readonly object AllLogsLock = new();
+ internal static readonly ConcurrentDictionary LogCounter = new();
+ private const int MAX_LOG = 10000;
+ private static int allLogsIndex;
+
+ private const int MaxLogExceptionPerHour = 1000;
+ private static int lastHour;
+ private static int exceptionCount;
+
+ internal static void TelemetryLogTrace(string log, SeverityLevel severityLevel, bool flush = false)
+ {
+ int logCount = LogCounter.AddOrUpdate(log, 1, (key, value) => value + 1);
+ Logger.Log(log);
+ }
+
+ internal static void Log(Exception e)
+ {
+ if (e is not KnownException)
+ {
+ string exText = e.ToString();
+
+ Log($"!Exception!: {exText}");
+
+ if (DateTime.UtcNow.Hour != lastHour)
+ {
+ lastHour = DateTime.UtcNow.Hour;
+ exceptionCount = 0;
+ }
+
+ if (exceptionCount < MaxLogExceptionPerHour)
+ {
+ exceptionCount++;
+ }
+ else if (exceptionCount != short.MaxValue)
+ {
+ exceptionCount = short.MaxValue;
+ }
+ }
+ }
+
+ private const string HeaderSENT =
+ "Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}";
+
+ private const string HeaderRECEIVED =
+ "Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}";
+
+ internal static void LogDebug(string log, bool clearLog = false)
+ {
+#if DEBUG
+ Log(log, clearLog);
+#endif
+ }
+
+ internal static void Log(string log, bool clearLog = false)
+ {
+ log = DateTime.Now.ToString("MM/dd HH:mm:ss.fff", CultureInfo.InvariantCulture) + $"({Thread.CurrentThread.ManagedThreadId})" + log;
+
+ ManagedCommon.Logger.LogInfo(log);
+ lock (AllLogsLock)
+ {
+ if (clearLog)
+ {
+ allLogsIndex = 0;
+ }
+
+ AllLogs[allLogsIndex] = log;
+ allLogsIndex = (allLogsIndex + 1) % MAX_LOG;
+ }
+ }
+
+ internal static void LogDebug(string format, params object[] args)
+ {
+#if DEBUG
+ Logger.Log(format, args);
+#endif
+ }
+
+ private static void Log(string format, params object[] args)
+ {
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, format, args));
+ }
+
+ private static PackageMonitor lastPackageSent;
+ private static PackageMonitor lastPackageReceived;
+
+ [Conditional("DEBUG")]
+ internal static void LogAll()
+ {
+ string log;
+
+ if (!lastPackageSent.Equals(Common.PackageSent))
+ {
+ log = string.Format(
+ CultureInfo.CurrentCulture,
+ "SENT:" + HeaderSENT,
+ Common.PackageSent.Heartbeat,
+ Common.PackageSent.Keyboard,
+ Common.PackageSent.Mouse,
+ Common.PackageSent.Hello,
+ Common.PackageSent.Matrix,
+ Common.PackageSent.ClipboardText,
+ Common.PackageSent.ClipboardImage,
+ Common.PackageSent.ByeBye,
+ Common.PackageSent.Clipboard,
+ Common.PackageSent.ClipboardDragDrop,
+ Common.PackageSent.ClipboardDragDropEnd,
+ Common.PackageSent.ExplorerDragDrop,
+ Common.inputEventCount,
+ Common.PackageSent.Nil);
+ Log(log);
+ lastPackageSent = Common.PackageSent; // Copy data
+ }
+
+ if (!lastPackageReceived.Equals(Common.PackageReceived))
+ {
+ log = string.Format(
+ CultureInfo.CurrentCulture,
+ "RECEIVED:" + HeaderRECEIVED,
+ Common.PackageReceived.Heartbeat,
+ Common.PackageReceived.Keyboard,
+ Common.PackageReceived.Mouse,
+ Common.PackageReceived.Hello,
+ Common.PackageReceived.Matrix,
+ Common.PackageReceived.ClipboardText,
+ Common.PackageReceived.ClipboardImage,
+ Common.PackageReceived.ByeBye,
+ Common.PackageReceived.Clipboard,
+ Common.PackageReceived.ClipboardDragDrop,
+ Common.PackageReceived.ClipboardDragDropEnd,
+ Common.PackageReceived.ExplorerDragDrop,
+ Common.invalidPackageCount,
+ Common.PackageReceived.Nil,
+ Common.processedPackageCount,
+ Common.skippedPackageCount);
+ Log(log);
+ lastPackageReceived = Common.PackageReceived;
+ }
+ }
+
+ internal static void GenerateLog()
+ {
+ int l = Setting.Values.DumpObjectsLevel;
+ if (l is > 0 and < 10)
+ {
+ Logger.DumpObjects(l);
+ }
+ }
+
+ private static List myThreads;
+
+ internal static void DumpObjects(int level)
+ {
+ try
+ {
+ string logFile = Path.Combine(Common.RunWithNoAdminRight ? Path.GetTempPath() : Path.GetDirectoryName(Application.ExecutablePath), "MagicMouse.log");
+
+ StringBuilder sb = new(1000000);
+ string log;
+
+ myThreads = new List();
+
+ foreach (ProcessThread t in Process.GetCurrentProcess().Threads)
+ {
+ myThreads.Add(t);
+ }
+
+ _ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
+ _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
+ sb.AppendLine("[Logger]\r\n===============");
+ Logger.DumpType(sb, typeof(Logger), 0, level);
+
+ log = string.Format(
+ CultureInfo.CurrentCulture,
+ "{0} {1}\r\n{2}\r\n\r\n{3}",
+ Application.ProductName,
+ Application.ProductVersion,
+ "Private Mem: " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString(CultureInfo.CurrentCulture) + "KB",
+ sb.ToString());
+
+ if (!string.IsNullOrEmpty(Common.myKey))
+ {
+ log = log.Replace(Common.MyKey, Common.GetDebugInfo(Common.MyKey));
+ }
+
+ log += Thread.DumpThreadsStack();
+ log += $"\r\nCurrent process session: {Process.GetCurrentProcess().SessionId}, active console session: {NativeMethods.WTSGetActiveConsoleSessionId()}.";
+
+ File.WriteAllText(logFile, log);
+
+ if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
+ {
+ _ = MessageBox.Show("Dump file created: " + logFile, Application.ProductName);
+ }
+ else
+ {
+ Common.ShowToolTip("Dump file created: " + logFile + " and placed in the Clipboard.", 10000);
+ Clipboard.SetText(logFile);
+ }
+ }
+ catch (Exception e)
+ {
+ _ = MessageBox.Show(e.Message + "\r\n" + e.StackTrace, Application.ProductName);
+ }
+ }
+
+ internal static bool PrivateDump(StringBuilder sb, object obj, string objName, int level, int maxLevel, bool stop)
+ {
+ Type t;
+ string padStr = string.Empty;
+ string[] strArr;
+ string objString;
+
+ if (obj == null || (maxLevel >= 0 && level >= maxLevel) || obj is Cursor)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < level; i++)
+ {
+ padStr += i < level - 1 ? "-" : padStr += string.Empty;
+ }
+
+ objString = obj.ToString();
+ t = obj.GetType();
+ strArr = new string[7];
+ strArr[0] = padStr;
+ strArr[1] = objName;
+
+ // strArr[2] = " ";
+ // strArr[3] = t.FullName;
+ strArr[4] = " = ";
+ strArr[5] = objName.Equals("myKey", StringComparison.OrdinalIgnoreCase)
+ ? Common.GetDebugInfo(objString)
+ : objName.Equals("lastClipboardObject", StringComparison.OrdinalIgnoreCase)
+ ? string.Empty
+ : objString
+ .Replace("System.Windows.Forms.", string.Empty)
+ .Replace("System.Net.Sockets.", string.Empty)
+ .Replace("System.Security.Cryptography.", string.Empty)
+ .Replace("System.Threading.", string.Empty)
+ .Replace("System.ComponentModel.", string.Empty)
+ .Replace("System.Runtime.", string.Empty)
+ .Replace("System.Drawing.", string.Empty)
+ .Replace("System.Object", "O")
+ .Replace("System.Diagnostics.", string.Empty)
+ .Replace("System.Collections.", string.Empty)
+ .Replace("System.Drawing.", string.Empty)
+ .Replace("System.Int", string.Empty)
+ .Replace("System.EventHandler.", string.Empty);
+ strArr[6] = "\r\n";
+ _ = sb.Append(string.Concat(strArr).Replace(Common.BinaryName, "MM"));
+
+ if (stop || t.IsPrimitive)
+ {
+ return false;
+ }
+
+ Logger.DumpObject(sb, obj, level, t, maxLevel);
+ return true;
+ }
+
+ internal static void DumpObject(StringBuilder sb, object obj, int level, Type t, int maxLevel)
+ {
+ int i;
+ bool stop;
+ if (t == typeof(Delegate))
+ {
+ return;
+ }
+
+ FieldInfo[] fi;
+ string type;
+
+ if (obj is PackageType or string or AddressFamily or ID or IPAddress)
+ {
+ return;
+ }
+
+ type = obj.GetType().ToString();
+
+ if (type.EndsWith("type", StringComparison.CurrentCultureIgnoreCase) || type.Contains("Cryptography")
+ || type.EndsWith("AsyncEventBits", StringComparison.CurrentCultureIgnoreCase))
+ {
+ return;
+ }
+
+ stop = obj == null || obj is DATA || obj.GetType().BaseType == typeof(ValueType)
+ || obj.GetType().Namespace.Contains("System.Windows");
+ fi = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
+
+ foreach (FieldInfo f in fi)
+ {
+ if (f.GetValue(obj) != AllLogs)
+ {
+ _ = PrivateDump(sb, f.GetValue(obj), f.Name, level + 1, maxLevel, stop);
+ }
+ }
+
+ if (obj is Dictionary>)
+ {
+ Dictionary> d = obj as Dictionary>;
+
+ foreach (string k in d.Keys)
+ {
+ if (d.TryGetValue(k, out List l))
+ {
+ foreach (IPAddress ip in l)
+ {
+ _ = PrivateDump(sb, ip, "[" + k + "]", level + 1, maxLevel, false);
+ }
+ }
+ }
+ }
+
+ if (obj is Array)
+ {
+ try
+ {
+ if (obj is MachineInf[])
+ {
+ MachineInf[] os = (MachineInf[])obj;
+
+ for (i = 0; i < os.GetLength(0); i++)
+ {
+ _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
+ }
+ }
+ else if (obj is int[] || obj is uint[])
+ {
+ int[] os = (int[])obj;
+
+ for (i = 0; i < os.GetLength(0); i++)
+ {
+ _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
+ }
+ }
+ else if (obj is short[] || obj is ushort[])
+ {
+ short[] os = (short[])obj;
+
+ for (i = 0; i < os.GetLength(0); i++)
+ {
+ _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
+ }
+ }
+ else if (obj is TcpClient[] || obj is IPAddress[] || obj is TcpSk[] || obj is string[]
+ || obj is TcpServer[]
+ || obj is ProcessThread[] || obj is Thread[])
+ {
+ object[] os = (object[])obj;
+
+ for (i = 0; i < os.GetLength(0); i++)
+ {
+ _ = PrivateDump(sb, os[i], "[" + i + "]", level + 1, maxLevel, false);
+ }
+ }
+ else
+ {
+ _ = PrivateDump(sb, obj.GetType().ToString() + ": N/A", obj.GetType().ToString(), level + 1, maxLevel, false);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ internal static void DumpType(StringBuilder sb, Type typeToDump, int level, int maxLevel)
+ {
+ if ((typeToDump == typeof(Delegate))
+ || (typeToDump == typeof(PackageType))
+ || (typeToDump == typeof(string))
+ || (typeToDump == typeof(AddressFamily))
+ || (typeToDump == typeof(ID))
+ || (typeToDump == typeof(IPAddress)))
+ {
+ return;
+ }
+
+ var typeFullName = typeToDump.ToString();
+ if (typeFullName.EndsWith("type", StringComparison.CurrentCultureIgnoreCase)
+ || typeFullName.Contains("Cryptography")
+ || typeFullName.EndsWith("AsyncEventBits", StringComparison.CurrentCultureIgnoreCase))
+ {
+ return;
+ }
+
+ var stop = (typeToDump == null)
+ || (typeToDump == typeof(DATA))
+ || (typeToDump.BaseType == typeof(ValueType))
+ || typeToDump.Namespace.Contains("System.Windows");
+
+ var fieldInfos = typeToDump.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
+ foreach (var fieldInfo in fieldInfos)
+ {
+ if (fieldInfo.GetValue(null) != AllLogs)
+ {
+ _ = Logger.PrivateDump(sb, fieldInfo.GetValue(null), fieldInfo.Name, level + 1, maxLevel, stop);
+ }
+ }
+ }
+
+ internal static string GetStackTrace(StackTrace st)
+ {
+ string rv = string.Empty;
+
+ for (int i = 0; i < st.FrameCount; i++)
+ {
+ StackFrame sf = st.GetFrame(i);
+ rv += sf.GetMethod() + " <= ";
+ }
+
+ return rv;
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsForm.cs b/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsForm.cs
index c8977b782a..768e0bdadc 100644
--- a/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsForm.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsForm.cs
@@ -5,7 +5,7 @@
using System;
using System.Drawing;
using System.Windows.Forms;
-
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Form.Settings;
namespace MouseWithoutBorders
@@ -23,9 +23,9 @@ namespace MouseWithoutBorders
toolTipManual.ToolTipTitle = Application.ProductName;
Text = Application.ProductName;
- Common.LogDebug("FIRST RUN, SHOWING THE FIRST SETUP PAGE.");
+ Logger.LogDebug("FIRST RUN, SHOWING THE FIRST SETUP PAGE.");
- Common.LogDebug($"{nameof(Common.RunWithNoAdminRight)} = {Common.RunWithNoAdminRight}");
+ Logger.LogDebug($"{nameof(Common.RunWithNoAdminRight)} = {Common.RunWithNoAdminRight}");
if (Common.RunWithNoAdminRight)
{
@@ -43,7 +43,7 @@ namespace MouseWithoutBorders
if (_currentPage != null)
{
- Common.LogDebug(_currentPage.Name + " closing.");
+ Logger.LogDebug(_currentPage.Name + " closing.");
_currentPage.OnPageClosing();
}
@@ -67,7 +67,7 @@ namespace MouseWithoutBorders
if (page != null)
{
- Common.LogDebug("GOING TO NEXT PAGE: " + page.Name);
+ Logger.LogDebug("GOING TO NEXT PAGE: " + page.Name);
page.BackColor = Color.Transparent;
page.NextPage += PageNextPage;
page.Location = contentPanel.Location;
diff --git a/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage3a.cs b/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage3a.cs
index bd08682585..4c8c3cd2eb 100644
--- a/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage3a.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage3a.cs
@@ -7,6 +7,7 @@ using System.Drawing;
using System.Windows.Forms;
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Properties;
namespace MouseWithoutBorders
@@ -42,7 +43,7 @@ namespace MouseWithoutBorders
private void ShowStatus(string status)
{
labelStatus.Text = status;
- Common.Log(status);
+ Logger.Log(status);
}
public override void OnPageClosing()
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs b/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
index fdb76ed901..edd35035ad 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
@@ -16,6 +16,7 @@ using System.Windows.Forms;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.frmInputCallback.#InstallKeyboardAndMouseHook()", Justification = "Dotnet port with style preservation")]
@@ -65,7 +66,7 @@ namespace MouseWithoutBorders
Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Common.MouseEvent);
Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Common.KeybdEvent);
- Common.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
+ Logger.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
/* The hook is called in the context of the thread that installed it.
* The call is made by sending a message to the thread that installed the hook.
* Therefore, the thread that installed the hook must have a message loop!!!
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
index d00215e01a..fff0199069 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
@@ -21,7 +21,7 @@ using Microsoft.PowerToys.Telemetry;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
-
+using MouseWithoutBorders.Core;
using Timer = System.Windows.Forms.Timer;
[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#buttonOK_Click(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
@@ -151,7 +151,7 @@ namespace MouseWithoutBorders
if (Common.MachineMatrix != null && Common.MachineMatrix.Length == Common.MAX_MACHINE)
{
- Common.LogDebug("LoadMachines: Machine Matrix: " + Setting.Values.MachineMatrixString);
+ Logger.LogDebug("LoadMachines: Machine Matrix: " + Setting.Values.MachineMatrixString);
for (int i = 0; i < Common.MAX_MACHINE; i++)
{
@@ -329,8 +329,8 @@ namespace MouseWithoutBorders
}
catch (Exception ee)
{
- Common.Log(ee);
- Common.Log(rv.ToString(CultureInfo.CurrentCulture));
+ Logger.Log(ee);
+ Logger.Log(rv.ToString(CultureInfo.CurrentCulture));
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
index bf79bef841..0df3454d80 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
@@ -22,6 +22,7 @@ using Microsoft.PowerToys.Telemetry;
// 2023- Included in PowerToys.
//
using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Core;
using MouseWithoutBorders.Properties;
using Timer = System.Windows.Forms.Timer;
@@ -81,7 +82,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -232,7 +233,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -273,7 +274,7 @@ namespace MouseWithoutBorders
{
BackColor = Color.White;
Opacity = 0.15;
- Common.Log(ex);
+ Logger.Log(ex);
}
helperTimer = new System.Windows.Forms.Timer();
@@ -355,7 +356,7 @@ namespace MouseWithoutBorders
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Common.GetUserName())
{
// While Windows 8 is hybrid-shutting down, user name would be empty (as returned from the .Net API), we should not do anything in this case.
- Common.LogDebug("No active user.");
+ Logger.LogDebug("No active user.");
Thread.Sleep(1000);
busy = false;
return;
@@ -432,7 +433,7 @@ namespace MouseWithoutBorders
if (!Common.AtLeastOneSocketEstablished())
{
Common.GetMachineName();
- Common.LogDebug("Common.pleaseReopenSocket: " + Common.PleaseReopenSocket.ToString(CultureInfo.InvariantCulture));
+ Logger.LogDebug("Common.pleaseReopenSocket: " + Common.PleaseReopenSocket.ToString(CultureInfo.InvariantCulture));
Common.ReopenSockets(false);
Common.NewDesMachineID = Common.DesMachineID = Common.MachineID;
}
@@ -545,7 +546,7 @@ namespace MouseWithoutBorders
if (count % 20 == 0)
{
- Common.LogAll();
+ Logger.LogAll();
// Need to review this code on why it is needed (moved from MoveToMyNeighbourIfNeeded(...))
for (int i = 0; i < Common.MachineMatrix.Length; i++)
@@ -579,14 +580,14 @@ namespace MouseWithoutBorders
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Common.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
{
- Common.TelemetryLogTrace($"{Common.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"{Common.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
}
}
}
}
catch (Exception ex)
{
- Common.Log(ex);
+ Logger.Log(ex);
}
finally
{
@@ -678,7 +679,7 @@ namespace MouseWithoutBorders
p.Dispose();
#endif
- Common.LogDebug($"Changing icon to {iconCode}.");
+ Logger.LogDebug($"Changing icon to {iconCode}.");
if (NotifyIcon.Icon != null)
{
@@ -690,13 +691,13 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
internal void MenuAllPC_Click(object sender, EventArgs e)
{
- Common.LogDebug("menuAllPC_Click");
+ Logger.LogDebug("menuAllPC_Click");
Common.SwitchToMultipleMode(MenuAllPC.Checked, true);
CurIcon = MenuAllPC.Checked ? Common.ICON_ALL : Common.ICON_ONE;
ChangeIcon(CurIcon);
@@ -801,7 +802,7 @@ namespace MouseWithoutBorders
if (h.ToInt32() > 0)
{
- Common.LogDebug("Hide Mouse Without Borders Helper.");
+ Logger.LogDebug("Hide Mouse Without Borders Helper.");
// Common.ShowWindow(h, 1);
_ = NativeMethods.ShowWindow(h, 0);
@@ -813,7 +814,7 @@ namespace MouseWithoutBorders
break;
case NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP:
- Common.LogDebug("Got WM_CHECK_EXPLORER_DRAG_DROP!");
+ Logger.LogDebug("Got WM_CHECK_EXPLORER_DRAG_DROP!");
Common.DragDropStep04();
break;
@@ -825,7 +826,7 @@ namespace MouseWithoutBorders
break;
case WM_QUERYENDSESSION:
- Common.LogDebug("WM_QUERYENDSESSION...");
+ Logger.LogDebug("WM_QUERYENDSESSION...");
Common.StartServiceAndSendLogoffSignal();
break;
@@ -993,7 +994,7 @@ namespace MouseWithoutBorders
}
catch (Exception e)
{
- Common.Log(e);
+ Logger.Log(e);
}
}
@@ -1210,7 +1211,7 @@ namespace MouseWithoutBorders
private void MenuGenDumpFile_Click(object sender, EventArgs e)
{
- Common.GenerateLog();
+ Logger.GenerateLog();
}
private void MainMenu_Opening(object sender, CancelEventArgs e)
diff --git a/src/modules/MouseWithoutBorders/App/Helper/FormHelper.cs b/src/modules/MouseWithoutBorders/App/Helper/FormHelper.cs
index f36bd0292a..969ba9db37 100644
--- a/src/modules/MouseWithoutBorders/App/Helper/FormHelper.cs
+++ b/src/modules/MouseWithoutBorders/App/Helper/FormHelper.cs
@@ -100,7 +100,7 @@ namespace MouseWithoutBorders
if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
- Logger.LogEvent(Application.ProductName + " cannot be used in a remote desktop or virtual machine session.");
+ EventLogger.LogEvent(Application.ProductName + " cannot be used in a remote desktop or virtual machine session.");
}
else
{
@@ -135,7 +135,7 @@ namespace MouseWithoutBorders
}
catch (Exception ex)
{
- Logger.LogEvent("FormHelper_DragEnter: " + ex.Message, EventLogEntryType.Error);
+ EventLogger.LogEvent("FormHelper_DragEnter: " + ex.Message, EventLogEntryType.Error);
QuitDueToCommunicationError();
}
}
@@ -164,11 +164,11 @@ namespace MouseWithoutBorders
{
try
{
- Logger.LogEvent(log, EventLogEntryType.Warning);
+ EventLogger.LogEvent(log, EventLogEntryType.Warning);
}
catch (Exception e)
{
- Logger.LogEvent(log + " ==> SendLog Exception: " + e.Message, EventLogEntryType.Warning);
+ EventLogger.LogEvent(log + " ==> SendLog Exception: " + e.Message, EventLogEntryType.Warning);
}
}
@@ -343,7 +343,7 @@ namespace MouseWithoutBorders
}
catch (Exception ex)
{
- Logger.LogEvent("WM_DRAWCLIPBOARD: " + ex.Message, EventLogEntryType.Error);
+ EventLogger.LogEvent("WM_DRAWCLIPBOARD: " + ex.Message, EventLogEntryType.Error);
QuitDueToCommunicationError();
}
diff --git a/src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj b/src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj
index 9a4e8acb82..705340f39f 100644
--- a/src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj
+++ b/src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj
@@ -57,6 +57,8 @@
+
+
diff --git a/src/modules/MouseWithoutBorders/App/Helper/Program.cs b/src/modules/MouseWithoutBorders/App/Helper/Program.cs
index 7a3ae0424b..874a0ac2a4 100644
--- a/src/modules/MouseWithoutBorders/App/Helper/Program.cs
+++ b/src/modules/MouseWithoutBorders/App/Helper/Program.cs
@@ -8,6 +8,7 @@ using System.IO;
using System.Windows.Forms;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
namespace MouseWithoutBorders
{
@@ -38,8 +39,11 @@ namespace MouseWithoutBorders
return;
}
+ ETWTrace etwTrace = new ETWTrace();
+
RunnerHelper.WaitForPowerToysRunnerExitFallback(() =>
{
+ etwTrace?.Dispose();
Application.Exit();
});
@@ -76,6 +80,8 @@ namespace MouseWithoutBorders
dotForm = new FormDot();
Application.Run(FormHelper = new FormHelper());
+
+ etwTrace?.Dispose();
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj b/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj
index 5e90e1c6e8..8bb21597d5 100644
--- a/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj
+++ b/src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj
@@ -208,6 +208,8 @@
+
+
diff --git a/src/modules/MouseWithoutBorders/App/Properties/AssemblyInfo.cs b/src/modules/MouseWithoutBorders/App/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..b031b89509
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+// 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.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("MouseWithoutBorders.UnitTests")]
diff --git a/src/modules/MouseWithoutBorders/App/Service/MouseWithoutBordersService.csproj b/src/modules/MouseWithoutBorders/App/Service/MouseWithoutBordersService.csproj
index 63a0f43823..3925634618 100644
--- a/src/modules/MouseWithoutBorders/App/Service/MouseWithoutBordersService.csproj
+++ b/src/modules/MouseWithoutBorders/App/Service/MouseWithoutBordersService.csproj
@@ -61,6 +61,8 @@
+
+
diff --git a/src/modules/MouseWithoutBorders/ModuleInterface/dllmain.cpp b/src/modules/MouseWithoutBorders/ModuleInterface/dllmain.cpp
index d2203e6ff5..463d527230 100644
--- a/src/modules/MouseWithoutBorders/ModuleInterface/dllmain.cpp
+++ b/src/modules/MouseWithoutBorders/ModuleInterface/dllmain.cpp
@@ -22,13 +22,13 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID /*lpRese
{
case DLL_PROCESS_ATTACH:
g_hInst_MouseWithoutBorders = hModule;
- Trace::RegisterProvider();
+ Trace::MouseWithoutBorders::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
- Trace::UnregisterProvider();
+ Trace::MouseWithoutBorders::UnregisterProvider();
break;
}
return TRUE;
diff --git a/src/modules/MouseWithoutBorders/ModuleInterface/pch.h b/src/modules/MouseWithoutBorders/ModuleInterface/pch.h
index cb0737a69d..0270a7bc39 100644
--- a/src/modules/MouseWithoutBorders/ModuleInterface/pch.h
+++ b/src/modules/MouseWithoutBorders/ModuleInterface/pch.h
@@ -9,8 +9,6 @@
#include
#include
#include
-#include
-#include
#include
#include
diff --git a/src/modules/MouseWithoutBorders/ModuleInterface/trace.cpp b/src/modules/MouseWithoutBorders/ModuleInterface/trace.cpp
index fb2f631bc6..7986ceefa4 100644
--- a/src/modules/MouseWithoutBorders/ModuleInterface/trace.cpp
+++ b/src/modules/MouseWithoutBorders/ModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
// Telemetry strings should not be localized.
#define LoggingProviderKey "Microsoft.PowerToys"
@@ -14,19 +16,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::MouseWithoutBorders::Enable(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventEnableMouseWithoutBordersKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -36,7 +28,7 @@ void Trace::MouseWithoutBorders::Enable(bool enabled) noexcept
void Trace::MouseWithoutBorders::ToggleServiceRegistration(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseWithoutBorders_ToggleServiceRegistration",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -46,7 +38,7 @@ void Trace::MouseWithoutBorders::ToggleServiceRegistration(bool enabled) noexcep
void Trace::MouseWithoutBorders::Activate() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseWithoutBorders_Activate",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -56,7 +48,7 @@ void Trace::MouseWithoutBorders::Activate() noexcept
// Log that the user tried to activate the editor
void Trace::MouseWithoutBorders::AddFirewallRule() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"MouseWithoutBorders_AddFirewallRule",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/MouseWithoutBorders/ModuleInterface/trace.h b/src/modules/MouseWithoutBorders/ModuleInterface/trace.h
index 1f9099eaae..ecd27cbd2d 100644
--- a/src/modules/MouseWithoutBorders/ModuleInterface/trace.h
+++ b/src/modules/MouseWithoutBorders/ModuleInterface/trace.h
@@ -1,12 +1,11 @@
#pragma once
+#include
+
class Trace
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
- class MouseWithoutBorders
+ class MouseWithoutBorders : public telemetry::TraceBase
{
public:
static void Enable(bool enabled) noexcept;
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
new file mode 100644
index 0000000000..1a20c67b31
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
@@ -0,0 +1,404 @@
+[Program logs]
+===============
+ = System.String[]
+[Other Logs]
+===============
+ = MouseWithoutBorders.Common
+lastClipboardEventTime = 0
+clipboardCopiedTime = 0
+Comma = System.Char[]
+--System.Char[] = System.Char[]: N/A
+Star = System.Char[]
+--System.Char[] = System.Char[]: N/A
+NullSeparator = System.Char[]
+--System.Char[] = System.Char[]: N/A
+k__BackingField = NONE
+k__BackingField = 0
+k__BackingField = False
+lastClipboardObject =
+k__BackingField = False
+ClipboardThreadOldLock = O
+screenWidth = 0
+screenHeight = 0
+lastX = 0
+lastY = 0
+mainFormVisible = True
+runOnLogonDesktop = False
+runOnScrSaverDesktop = False
+toggleIconsIndex = 0
+EvSwitch = EventWaitHandle
+lastPos = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+switchCount = 0
+lastReconnectByHotKeyTime = 0
+tcpPort = 0
+secondOpenSocketTry = False
+binaryName = MM
+k__BackingField = 0
+k__BackingField = False
+k__BackingField = False
+socketMutexBalance = 0
+k__BackingField = False
+k__BackingField = 0
+k__BackingField = 0
+InputSimulationLock = O
+lastSendNextMachine = 0
+lastInputEventCount = 0
+lastRealInputEventCount = 0
+minSendTime = 9223372036854775807
+avgSendTime = 0
+maxSendTime = 0
+totalSendCount = 0
+totalSendTime = 0
+isDragging = False
+dragDropStep05ExCalledByIpc = 0
+isDropping = False
+dragMachine = NONE
+k__BackingField = False
+magicNumber = 0
+ran = System.Random
+--_impl = System.Random+XoshiroImpl
+----_s0 = ????????????
+----_s1 = ????????????
+----_s2 = ????????????
+----_s3 = ????????????
+--k__BackingField = System.Random+ThreadSafeRandom
+InitialIV = ????????????
+k__BackingField = False
+k__BackingField = False
+LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]]
+--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]]
+----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer
+----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]
+------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A
+----_fastModBucketsMultiplier = 498560650640798693
+----_locks = O[]
+------System.Object[] = O[]: N/A
+----_countPerLock = 32[]
+------[0] = 0
+------[1] = 0
+------[2] = 0
+------[3] = 0
+------[4] = 0
+------[5] = 0
+------[6] = 0
+------[7] = 0
+------[8] = 0
+------[9] = 0
+------[10] = 0
+------[11] = 0
+------[12] = 0
+------[13] = 0
+------[14] = 0
+------[15] = 0
+--_budget = 2
+--_growLockArray = True
+--_comparerIsDefaultForClasses = False
+KeybdPackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+MousePackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+inputEventCount = 0
+invalidPackageCount = 0
+MOVE_MOUSE_RELATIVE = 100000
+XY_BY_PIXEL = 300000
+k__BackingField = 0
+actualLastPos = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+myLastX = 0
+myLastY = 0
+signalHelperToExit = False
+signalWatchDogToExit = False
+WndProcCounter = 0
+initDone = False
+REOPEN_WHEN_WSAECONNRESET = -10054
+REOPEN_WHEN_HOTKEY = -10055
+PleaseReopenSocket = 0
+ReopenSocketDueToReadError = False
+k__BackingField = ????????????
+--_dateData = ????????????
+--MinValue = 01/01/0001 00:00:00
+--MaxValue = 31/12/9999 23:59:59
+--UnixEpoch = 01/01/1970 00:00:00
+lastReleaseAllKeysCall = 0
+McMatrixLock = O
+desMachineID = NONE
+DesMachineName =
+newDesMachineID = NONE
+newDesMachineIdEx = NONE
+dropMachineID = NONE
+lastJump = ????????????
+desktopBounds = MouseWithoutBorders.MyRectangle
+--Left = 0
+--Top = 0
+--Right = 0
+--Bottom = 0
+primaryScreenBounds = MouseWithoutBorders.MyRectangle
+--Left = 0
+--Top = 0
+--Right = 0
+--Bottom = 0
+SwitchLocation = MouseWithoutBorders.Class.MouseLocation
+--k__BackingField = 0
+--k__BackingField = 0
+--k__BackingField = 0
+PackageSent = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+PackageReceived = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+PackageID = 0
+QUEUE_SIZE = 50
+RecentProcessedPackageIDs = 32[]
+--[0] = 0
+--[1] = 0
+--[2] = 0
+--[3] = 0
+--[4] = 0
+--[5] = 0
+--[6] = 0
+--[7] = 0
+--[8] = 0
+--[9] = 0
+--[10] = 0
+--[11] = 0
+--[12] = 0
+--[13] = 0
+--[14] = 0
+--[15] = 0
+--[16] = 0
+--[17] = 0
+--[18] = 0
+--[19] = 0
+--[20] = 0
+--[21] = 0
+--[22] = 0
+--[23] = 0
+--[24] = 0
+--[25] = 0
+--[26] = 0
+--[27] = 0
+--[28] = 0
+--[29] = 0
+--[30] = 0
+--[31] = 0
+--[32] = 0
+--[33] = 0
+--[34] = 0
+--[35] = 0
+--[36] = 0
+--[37] = 0
+--[38] = 0
+--[39] = 0
+--[40] = 0
+--[41] = 0
+--[42] = 0
+--[43] = 0
+--[44] = 0
+--[45] = 0
+--[46] = 0
+--[47] = 0
+--[48] = 0
+--[49] = 0
+recentProcessedPackageIndex = 0
+processedPackageCount = 0
+skippedPackageCount = 0
+k__BackingField = 0
+lastXY = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+shownErrMessage = False
+lastStartServiceTime = ????????????
+--_dateData = ????????????
+--MinValue = 01/01/0001 00:00:00
+--MaxValue = 31/12/9999 23:59:59
+--UnixEpoch = 01/01/1970 00:00:00
+SensitivePoints = Generic.List`1[Point]
+--_items = Point[]
+----System.Drawing.Point[] = Point[]: N/A
+--_size = 0
+--_version = 0
+--s_emptyArray = Point[]
+----System.Drawing.Point[] = Point[]: N/A
+p = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+k__BackingField = False
+BIG_CLIPBOARD_DATA_TIMEOUT = 30000
+MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
+MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
+TEXT_HEADER_SIZE = 12
+DATA_SIZE = 48
+TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
+TOGGLE_ICONS_SIZE = 4
+ICON_ONE = 0
+ICON_ALL = 1
+ICON_SMALL_CLIPBOARD = 2
+ICON_BIG_CLIPBOARD = 3
+ICON_ERROR = 4
+JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
+NETWORK_STREAM_BUF_SIZE = 1048576
+SymAlBlockSize = 16
+PW_LENGTH = 16
+HELPER_FORM_TEXT = Mouse without Borders Helper
+HelperProcessName = PowerToys.MouseWithoutBordersHelper
+MAX_MACHINE = 4
+MAX_SOCKET = 8
+HEARTBEAT_TIMEOUT = 1500000
+SKIP_PIXELS = 1
+JUMP_PIXELS = 2
+PACKAGE_SIZE = 32
+PACKAGE_SIZE_EX = 64
+WP_PACKAGE_SIZE = 6
+KEYEVENTF_KEYDOWN = 1
+KEYEVENTF_KEYUP = 2
+WH_MOUSE = 7
+WH_KEYBOARD = 2
+WH_MOUSE_LL = 14
+WH_KEYBOARD_LL = 13
+WM_MOUSEMOVE = 512
+WM_LBUTTONDOWN = 513
+WM_RBUTTONDOWN = 516
+WM_MBUTTONDOWN = 519
+WM_XBUTTONDOWN = 523
+WM_LBUTTONUP = 514
+WM_RBUTTONUP = 517
+WM_MBUTTONUP = 520
+WM_XBUTTONUP = 524
+WM_LBUTTONDBLCLK = 515
+WM_RBUTTONDBLCLK = 518
+WM_MBUTTONDBLCLK = 521
+WM_MOUSEWHEEL = 522
+WM_KEYDOWN = 256
+WM_KEYUP = 257
+WM_SYSKEYDOWN = 260
+WM_SYSKEYUP = 261
+[Logger Logs]
+===============
+AllLogsLock = O
+LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32]
+--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,32]
+----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalComparer
+----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,32][]
+------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Int32][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,32][]: N/A
+----_fastModBucketsMultiplier = 498560650640798693
+----_locks = O[]
+------System.Object[] = O[]: N/A
+----_countPerLock = 32[]
+------[0] = 0
+------[1] = 0
+------[2] = 0
+------[3] = 0
+------[4] = 0
+------[5] = 0
+------[6] = 0
+------[7] = 0
+------[8] = 0
+------[9] = 0
+------[10] = 0
+------[11] = 0
+------[12] = 0
+------[13] = 0
+------[14] = 0
+------[15] = 0
+--_budget = 2
+--_growLockArray = True
+--_comparerIsDefaultForClasses = False
+allLogsIndex = 0
+lastHour = 0
+exceptionCount = 0
+lastPackageSent = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+lastPackageReceived = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+MAX_LOG = 10000
+MaxLogExceptionPerHour = 1000
+HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}
+HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.original.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.original.txt
new file mode 100644
index 0000000000..04346ea04a
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.original.txt
@@ -0,0 +1,405 @@
+[Other Logs]
+===============
+ = MouseWithoutBorders.Common
+lastClipboardEventTime = 0
+clipboardCopiedTime = 0
+Comma = System.Char[]
+--System.Char[] = System.Char[]: N/A
+Star = System.Char[]
+--System.Char[] = System.Char[]: N/A
+NullSeparator = System.Char[]
+--System.Char[] = System.Char[]: N/A
+k__BackingField = NONE
+k__BackingField = 0
+k__BackingField = False
+lastClipboardObject =
+k__BackingField = False
+ClipboardThreadOldLock = O
+screenWidth = 0
+screenHeight = 0
+lastX = 0
+lastY = 0
+mainFormVisible = True
+runOnLogonDesktop = False
+runOnScrSaverDesktop = False
+toggleIconsIndex = 0
+EvSwitch = EventWaitHandle
+lastPos = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+switchCount = 0
+lastReconnectByHotKeyTime = 0
+tcpPort = 0
+secondOpenSocketTry = False
+binaryName = MM
+k__BackingField = 0
+k__BackingField = False
+k__BackingField = False
+socketMutexBalance = 0
+k__BackingField = False
+k__BackingField = 0
+k__BackingField = 0
+InputSimulationLock = O
+lastSendNextMachine = 0
+lastInputEventCount = 0
+lastRealInputEventCount = 0
+minSendTime = 9223372036854775807
+avgSendTime = 0
+maxSendTime = 0
+totalSendCount = 0
+totalSendTime = 0
+isDragging = False
+dragDropStep05ExCalledByIpc = 0
+isDropping = False
+dragMachine = NONE
+k__BackingField = False
+magicNumber = 0
+ran = System.Random
+--_impl = System.Random+XoshiroImpl
+----_s0 = 7284351989338469498
+----_s1 = 15479097190878625043
+----_s2 = 10963166711904013490
+----_s3 = 8600427501468926680
+--k__BackingField = System.Random+ThreadSafeRandom
+InitialIV = 99999999999999999999
+k__BackingField = False
+k__BackingField = False
+LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]]
+--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]]
+----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer
+----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]
+------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A
+----_fastModBucketsMultiplier = 498560650640798693
+----_locks = O[]
+------System.Object[] = O[]: N/A
+----_countPerLock = 32[]
+------[0] = 0
+------[1] = 0
+------[2] = 0
+------[3] = 0
+------[4] = 0
+------[5] = 0
+------[6] = 0
+------[7] = 0
+------[8] = 0
+------[9] = 0
+------[10] = 0
+------[11] = 0
+------[12] = 0
+------[13] = 0
+------[14] = 0
+------[15] = 0
+--_budget = 2
+--_growLockArray = True
+--_comparerIsDefaultForClasses = False
+KeybdPackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+MousePackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+inputEventCount = 0
+invalidPackageCount = 0
+MOVE_MOUSE_RELATIVE = 100000
+XY_BY_PIXEL = 300000
+k__BackingField = 0
+actualLastPos = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+myLastX = 0
+myLastY = 0
+signalHelperToExit = False
+signalWatchDogToExit = False
+WndProcCounter = 0
+initDone = False
+REOPEN_WHEN_WSAECONNRESET = -10054
+REOPEN_WHEN_HOTKEY = -10055
+PleaseReopenSocket = 0
+ReopenSocketDueToReadError = False
+k__BackingField = 26/09/2024 20:35:51
+--_dateData = 5250315815941007823
+--MinValue = 01/01/0001 00:00:00
+--MaxValue = 31/12/9999 23:59:59
+--UnixEpoch = 01/01/1970 00:00:00
+lastReleaseAllKeysCall = 0
+AllLogsLock = O
+LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32]
+--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,32]
+----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalComparer
+----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,32][]
+------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Int32][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,32][]: N/A
+----_fastModBucketsMultiplier = 498560650640798693
+----_locks = O[]
+------System.Object[] = O[]: N/A
+----_countPerLock = 32[]
+------[0] = 0
+------[1] = 0
+------[2] = 0
+------[3] = 0
+------[4] = 0
+------[5] = 0
+------[6] = 0
+------[7] = 0
+------[8] = 0
+------[9] = 0
+------[10] = 0
+------[11] = 0
+------[12] = 0
+------[13] = 0
+------[14] = 0
+------[15] = 0
+--_budget = 2
+--_growLockArray = True
+--_comparerIsDefaultForClasses = False
+RepeatedLogIndexSelection = 32[]
+--[0] = 1
+--[1] = 3
+--[2] = 10
+--[3] = 50
+--[4] = 100
+allLogsIndex = 0
+lastHour = 0
+exceptionCount = 0
+p1 = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+p2 = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+McMatrixLock = O
+desMachineID = NONE
+DesMachineName =
+newDesMachineID = NONE
+newDesMachineIdEx = NONE
+dropMachineID = NONE
+lastJump = 63862983351362
+desktopBounds = MouseWithoutBorders.MyRectangle
+--Left = 0
+--Top = 0
+--Right = 0
+--Bottom = 0
+primaryScreenBounds = MouseWithoutBorders.MyRectangle
+--Left = 0
+--Top = 0
+--Right = 0
+--Bottom = 0
+SwitchLocation = MouseWithoutBorders.Class.MouseLocation
+--k__BackingField = 0
+--k__BackingField = 0
+--k__BackingField = 0
+PackageSent = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+PackageReceived = MouseWithoutBorders.PackageMonitor
+--Keyboard = 0
+--Mouse = 0
+--Heartbeat = 0
+--ByeBye = 0
+--Hello = 0
+--Matrix = 0
+--ClipboardText = 0
+--ClipboardImage = 0
+--Clipboard = 0
+--ClipboardDragDrop = 0
+--ClipboardDragDropEnd = 0
+--ClipboardAsk = 0
+--ExplorerDragDrop = 0
+--Nil = 0
+PackageID = 0
+QUEUE_SIZE = 50
+RecentProcessedPackageIDs = 32[]
+--[0] = 0
+--[1] = 0
+--[2] = 0
+--[3] = 0
+--[4] = 0
+--[5] = 0
+--[6] = 0
+--[7] = 0
+--[8] = 0
+--[9] = 0
+--[10] = 0
+--[11] = 0
+--[12] = 0
+--[13] = 0
+--[14] = 0
+--[15] = 0
+--[16] = 0
+--[17] = 0
+--[18] = 0
+--[19] = 0
+--[20] = 0
+--[21] = 0
+--[22] = 0
+--[23] = 0
+--[24] = 0
+--[25] = 0
+--[26] = 0
+--[27] = 0
+--[28] = 0
+--[29] = 0
+--[30] = 0
+--[31] = 0
+--[32] = 0
+--[33] = 0
+--[34] = 0
+--[35] = 0
+--[36] = 0
+--[37] = 0
+--[38] = 0
+--[39] = 0
+--[40] = 0
+--[41] = 0
+--[42] = 0
+--[43] = 0
+--[44] = 0
+--[45] = 0
+--[46] = 0
+--[47] = 0
+--[48] = 0
+--[49] = 0
+recentProcessedPackageIndex = 0
+processedPackageCount = 0
+skippedPackageCount = 0
+k__BackingField = 0
+lastXY = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+shownErrMessage = False
+lastStartServiceTime = 26/09/2024 20:35:51
+--_dateData = 5250315815941010854
+--MinValue = 01/01/0001 00:00:00
+--MaxValue = 31/12/9999 23:59:59
+--UnixEpoch = 01/01/1970 00:00:00
+SensitivePoints = Generic.List`1[Point]
+--_items = Point[]
+----System.Drawing.Point[] = Point[]: N/A
+--_size = 0
+--_version = 0
+--s_emptyArray = Point[]
+----System.Drawing.Point[] = Point[]: N/A
+p = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+k__BackingField = False
+BIG_CLIPBOARD_DATA_TIMEOUT = 30000
+MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
+MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
+TEXT_HEADER_SIZE = 12
+DATA_SIZE = 48
+TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
+TOGGLE_ICONS_SIZE = 4
+ICON_ONE = 0
+ICON_ALL = 1
+ICON_SMALL_CLIPBOARD = 2
+ICON_BIG_CLIPBOARD = 3
+ICON_ERROR = 4
+JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
+NETWORK_STREAM_BUF_SIZE = 1048576
+SymAlBlockSize = 16
+PW_LENGTH = 16
+HELPER_FORM_TEXT = Mouse without Borders Helper
+HelperProcessName = PowerToys.MouseWithoutBordersHelper
+MAX_LOG = 10000
+MaxLogExceptionPerHour = 1000
+HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}
+HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}
+MAX_MACHINE = 4
+MAX_SOCKET = 8
+HEARTBEAT_TIMEOUT = 1500000
+SKIP_PIXELS = 1
+JUMP_PIXELS = 2
+PACKAGE_SIZE = 32
+PACKAGE_SIZE_EX = 64
+WP_PACKAGE_SIZE = 6
+KEYEVENTF_KEYDOWN = 1
+KEYEVENTF_KEYUP = 2
+WH_MOUSE = 7
+WH_KEYBOARD = 2
+WH_MOUSE_LL = 14
+WH_KEYBOARD_LL = 13
+WM_MOUSEMOVE = 512
+WM_LBUTTONDOWN = 513
+WM_RBUTTONDOWN = 516
+WM_MBUTTONDOWN = 519
+WM_XBUTTONDOWN = 523
+WM_LBUTTONUP = 514
+WM_RBUTTONUP = 517
+WM_MBUTTONUP = 520
+WM_XBUTTONUP = 524
+WM_LBUTTONDBLCLK = 515
+WM_RBUTTONDBLCLK = 518
+WM_MBUTTONDBLCLK = 521
+WM_MOUSEWHEEL = 522
+WM_KEYDOWN = 256
+WM_KEYUP = 257
+WM_SYSKEYDOWN = 260
+WM_SYSKEYUP = 261
\ No newline at end of file
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
new file mode 100644
index 0000000000..be960b9a9b
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
@@ -0,0 +1,161 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Concurrent;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MouseWithoutBorders.Core;
+
+namespace MouseWithoutBorders.UnitTests.Core;
+
+public static class LoggerTests
+{
+ [TestClass]
+ public sealed class PrivateDumpTests
+ {
+ /*
+ [TestMethod]
+ public void PrivateDumpShouldGenerateExpectedOutput()
+ {
+ // this was used to create the contents of "Logger.PrivateDump.original.txt"
+ // when the "Core.Logger" class was "Common" in "Common.Log.cs"
+
+ // PrivateDump throws an ArgumentNullException if this is null
+ Common.BinaryName = "MyBinary.dll";
+
+ // magic number from Settings.cs
+ var dumpObjectsLevel = 6;
+
+ // copied from DumpObjects in Common.Log.cs
+ var sb = new StringBuilder(1000000);
+ var result = Common.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, dumpObjectsLevel, false);
+ var output = sb.ToString();
+ }
+ */
+
+ [TestMethod]
+ [Ignore(
+ "This test relies on internal details of the dotnet platform and is sensitive to " +
+ "the specific version of dotnet being used. As a result it's likely to fail if the " +
+ "\"expected\" result was generated with a different version to the version used to " +
+ "run the test, so we're going to ignore it in the CI build process.")]
+ public void PrivateDumpShouldGenerateExpectedOutput()
+ {
+ static string NormalizeLog(string log)
+ {
+ var lines = log.Split("\r\n");
+
+ // some parts of the PrivateDump output are impossible to reproduce -
+ // e.g. random numbers, system timestamps, thread ids, etc, so we'll mask them
+ var maskPrefixes = new string[]
+ {
+ "----_s0 = ",
+ "----_s1 = ",
+ "----_s2 = ",
+ "----_s3 = ",
+ "k__BackingField = ",
+ "--_dateData = ",
+ "lastJump = ",
+ "lastStartServiceTime = ",
+ "InitialIV = ",
+ };
+ for (var i = 0; i < lines.Length; i++)
+ {
+ foreach (var maskPrefix in maskPrefixes)
+ {
+ if (lines[i].StartsWith(maskPrefix, StringComparison.InvariantCulture))
+ {
+ // replace the trailing text with "?" characters
+ lines[i] = string.Concat(
+ lines[i].AsSpan(0, maskPrefix.Length),
+ new string('?', 12));
+ }
+ }
+ }
+
+ // hide some of the internals of concurrent dictionary lock tables
+ // as the size can vary across machines
+ var removeLines = new string[]
+ {
+ "------[8] = 0",
+ "------[9] = 0",
+ "------[10] = 0",
+ "------[11] = 0",
+ "------[12] = 0",
+ "------[13] = 0",
+ "------[14] = 0",
+ "------[15] = 0",
+ };
+ lines = lines.Where(line => !removeLines.Contains(line)).ToArray();
+
+ return string.Join("\r\n", lines);
+ }
+
+ // PrivateDump throws an ArgumentNullException if this is null
+ Common.BinaryName = "MyBinary.dll";
+
+ // default magic number from Settings.cs
+ var settingsDumpObjectsLevel = 6;
+
+ // get the expected test result from an embedded resource
+ var assembly = Assembly.GetExecutingAssembly();
+ var resourceName = $"{typeof(LoggerTests).Namespace}.Logger.PrivateDump.expected.txt";
+ using var stream = assembly.GetManifestResourceStream(resourceName)
+ ?? throw new InvalidOperationException();
+ using var streamReader = new StreamReader(stream);
+ var expected = streamReader.ReadToEnd();
+
+ // copied from DumpObjects in Common.Log.cs
+ var sb = new StringBuilder(1000000);
+ _ = Logger.PrivateDump(sb, Logger.AllLogs, "[Program logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
+ _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
+ sb.AppendLine("[Logger Logs]\r\n===============");
+ Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel);
+ var actual = sb.ToString();
+
+ expected = NormalizeLog(expected);
+ actual = NormalizeLog(actual);
+
+ // Azure DevOps truncates debug output which makes it hard to see where
+ // the expected and actual differ, so we need to write a custom error message
+ // so we can just focus on the differences between expected and actual
+ var expectedLines = expected.Split("\r\n");
+ var actualLines = actual.Split("\r\n");
+ for (var i = 0; i < Math.Min(expectedLines.Length, actualLines.Length); i++)
+ {
+ if (actualLines[i] != expectedLines[i])
+ {
+ var message = new StringBuilder();
+ message.AppendLine(CultureInfo.InvariantCulture, $"{nameof(actual)} and {nameof(expected)} differ at line {i}:");
+
+ message.AppendLine();
+ message.AppendLine($"{nameof(actual)}:");
+ for (var j = i; j < Math.Min(i + 5, actualLines.Length); j++)
+ {
+ message.AppendLine(CultureInfo.InvariantCulture, $"[{j}]: {actualLines[j]}:");
+ }
+
+ message.AppendLine();
+ message.AppendLine($"{nameof(expected)}:");
+ for (var j = i; j < Math.Min(i + 5, expectedLines.Length); j++)
+ {
+ message.AppendLine(CultureInfo.InvariantCulture, $"[{j}]: {expectedLines[j]}:");
+ }
+
+ var x = new ConcurrentDictionary(-1, 16);
+
+ Assert.Fail(message.ToString());
+ }
+ }
+
+ // finally, throw an exception if the two don't match
+ // just in case the above doesn't spot a difference
+ // (e.g. different number of lines in the output)
+ Assert.AreEqual(expected, actual);
+ }
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj
new file mode 100644
index 0000000000..ad95d818a1
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ enable
+ enable
+ Library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/NewShellExtensionContextMenu.vcxproj b/src/modules/NewPlus/NewShellExtensionContextMenu/NewShellExtensionContextMenu.vcxproj
index 9444e849c0..8d2e617579 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/NewShellExtensionContextMenu.vcxproj
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/NewShellExtensionContextMenu.vcxproj
@@ -167,6 +167,9 @@ MakeAppx.exe pack /d . /p $(OutDir)NewPlusPackage.msix /nv
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.cpp b/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.cpp
index 5ad3537bb2..878673826b 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.cpp
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.cpp
@@ -4,7 +4,10 @@
#include "dll_main.h"
#include "trace.h"
+#include
+
HMODULE module_instance_handle = 0;
+Shared::Trace::ETWTrace trace(L"NewPlusShellExtension");
BOOL APIENTRY DllMain(HMODULE module_handle, DWORD ul_reason_for_call, LPVOID reserved)
{
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.h b/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.h
index f6c4284a10..9e980caa0d 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.h
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/dll_main.h
@@ -1,3 +1,6 @@
#pragma once
-extern HMODULE module_instance_handle;
\ No newline at end of file
+#include
+
+extern HMODULE module_instance_handle;
+extern Shared::Trace::ETWTrace trace;
\ No newline at end of file
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/new_utilities.h b/src/modules/NewPlus/NewShellExtensionContextMenu/new_utilities.h
index 55bafb8b56..7ae46635a8 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/new_utilities.h
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/new_utilities.h
@@ -50,6 +50,12 @@ namespace newplus::utilities
return false;
}
+ inline bool is_directory(const std::filesystem::path path)
+ {
+ const auto entry = std::filesystem::directory_entry(path);
+ return entry.is_directory();
+ }
+
inline bool wstring_same_when_comparing_ignore_case(std::wstring stringA, std::wstring stringB)
{
transform(stringA.begin(), stringA.end(), stringA.begin(), towupper);
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu.cpp b/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu.cpp
index 148dffd952..47f93beac7 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu.cpp
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu.cpp
@@ -7,6 +7,7 @@ using namespace Microsoft::WRL;
// // Sub context menu command enumerator
shell_context_sub_menu::shell_context_sub_menu(const ComPtr site_of_folder)
{
+ trace.UpdateState(true);
this->site_of_folder = site_of_folder;
// Determine the New+ Template folder location
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu_item.cpp b/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu_item.cpp
index bdae885009..12e5f9cf5c 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu_item.cpp
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_sub_menu_item.cpp
@@ -63,16 +63,23 @@ IFACEMETHODIMP shell_context_sub_menu_item::GetState(_In_opt_ IShellItemArray* s
IFACEMETHODIMP shell_context_sub_menu_item::Invoke(_In_opt_ IShellItemArray*, _In_opt_ IBindCtx*) noexcept
{
+ HRESULT hr = S_OK;
try
{
+ trace.UpdateState(true);
+
// Determine target path of where context menu was displayed
const auto target_path_name = utilities::get_path_from_unknown_site(site_of_folder);
// Determine initial filename
std::filesystem::path source_fullpath = template_entry->path;
- std::filesystem::path target_fullpath = std::wstring(target_path_name)
- + L"\\"
- + this->template_entry->get_target_filename(!utilities::get_newplus_setting_hide_starting_digits());
+ std::filesystem::path target_fullpath = std::wstring(target_path_name);
+
+ // Only append name to target if source is not a directory
+ if (!utilities::is_directory(target_fullpath))
+ {
+ target_fullpath.append(this->template_entry->get_target_filename(!utilities::get_newplus_setting_hide_starting_digits()));
+ }
// Copy file and determine final filename
std::filesystem::path target_final_fullpath = this->template_entry->copy_object_to(GetActiveWindow(), target_fullpath);
@@ -86,16 +93,19 @@ IFACEMETHODIMP shell_context_sub_menu_item::Invoke(_In_opt_ IShellItemArray*, _I
this->template_entry->enter_rename_mode(site_of_folder, target_final_fullpath);
Trace::EventCopyTemplateResult(S_OK);
-
- return S_OK;
}
catch (const std::exception& ex)
{
Trace::EventCopyTemplateResult(S_FALSE);
Logger::error(ex.what());
+
+ hr = S_FALSE;
}
- return S_FALSE;
+ trace.Flush();
+ trace.UpdateState(false);
+
+ return hr;
}
IFACEMETHODIMP shell_context_sub_menu_item::GetFlags(_Out_ EXPCMDFLAGS* returned_flags)
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/template_item.cpp b/src/modules/NewPlus/NewShellExtensionContextMenu/template_item.cpp
index 3c863be18e..e644df5c85 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/template_item.cpp
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/template_item.cpp
@@ -67,12 +67,12 @@ std::filesystem::path template_item::copy_object_to(const HWND window_handle, co
{
// SHFILEOPSTRUCT wants the from and to paths to be terminated with two NULLs,
wchar_t double_terminated_path_from[MAX_PATH + 1] = { 0 };
- wcsncpy_s(double_terminated_path_from, this->path.c_str(), this->path.string().length());
- double_terminated_path_from[this->path.string().length() + 1] = 0;
+ wcsncpy_s(double_terminated_path_from, this->path.c_str(), this->path.wstring().length());
+ double_terminated_path_from[this->path.wstring().length() + 1] = 0;
wchar_t double_terminated_path_to[MAX_PATH + 1] = { 0 };
- wcsncpy_s(double_terminated_path_to, destination.c_str(), destination.string().length());
- double_terminated_path_to[destination.string().length() + 1] = 0;
+ wcsncpy_s(double_terminated_path_to, destination.c_str(), destination.wstring().length());
+ double_terminated_path_to[destination.wstring().length() + 1] = 0;
SHFILEOPSTRUCT file_operation_params = { 0 };
file_operation_params.wFunc = FO_COPY;
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/trace.cpp b/src/modules/NewPlus/NewShellExtensionContextMenu/trace.cpp
index 0def375024..3a2c8c8c91 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/trace.cpp
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/trace.cpp
@@ -10,19 +10,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::EventToggleOnOff(_In_ const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"NewPlus_EventToggleOnOff",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -32,7 +22,7 @@ void Trace::EventToggleOnOff(_In_ const bool enabled) noexcept
void Trace::EventChangedTemplateLocation() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"NewPlus_ChangedTemplateLocation",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -41,7 +31,7 @@ void Trace::EventChangedTemplateLocation() noexcept
void Trace::EventShowTemplateItems(const size_t number_of_templates) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"NewPlus_EventShowTemplateItems",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -51,7 +41,7 @@ void Trace::EventShowTemplateItems(const size_t number_of_templates) noexcept
void Trace::EventCopyTemplate(_In_ const std::wstring template_file_extension) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"NewPlus_EventCopyTemplate",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -61,7 +51,7 @@ void Trace::EventCopyTemplate(_In_ const std::wstring template_file_extension) n
void Trace::EventCopyTemplateResult(_In_ const HRESULT hr) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"NewPlus_EventCopyTemplateResult",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/NewPlus/NewShellExtensionContextMenu/trace.h b/src/modules/NewPlus/NewShellExtensionContextMenu/trace.h
index 2d87e88588..7c21086642 100644
--- a/src/modules/NewPlus/NewShellExtensionContextMenu/trace.h
+++ b/src/modules/NewPlus/NewShellExtensionContextMenu/trace.h
@@ -2,11 +2,11 @@
#include "pch.h"
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
static void EventToggleOnOff(_In_ const bool new_enabled_state) noexcept;
static void EventChangedTemplateLocation() noexcept;
static void EventShowTemplateItems(_In_ const size_t number_of_templates) noexcept;
diff --git a/src/modules/PowerOCR/PowerOCR/App.xaml.cs b/src/modules/PowerOCR/PowerOCR/App.xaml.cs
index eab9acd8cd..77987ab5cd 100644
--- a/src/modules/PowerOCR/PowerOCR/App.xaml.cs
+++ b/src/modules/PowerOCR/PowerOCR/App.xaml.cs
@@ -6,10 +6,12 @@ using System;
using System.Globalization;
using System.Threading;
using System.Windows;
-
+using Common.UI;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
using PowerOCR.Keyboard;
using PowerOCR.Settings;
+using PowerToys.Interop;
namespace PowerOCR;
@@ -22,6 +24,7 @@ public partial class App : Application, IDisposable
private EventMonitor? eventMonitor;
private Mutex? _instanceMutex;
private int _powerToysRunnerPid;
+ private ETWTrace etwTrace = new ETWTrace();
private CancellationTokenSource NativeThreadCTS { get; set; }
@@ -43,12 +46,19 @@ public partial class App : Application, IDisposable
}
NativeThreadCTS = new CancellationTokenSource();
+
+ NativeEventWaiter.WaitForEventLoop(
+ Constants.TerminatePowerOCRSharedEvent(),
+ this.Shutdown,
+ this.Dispatcher,
+ NativeThreadCTS.Token);
}
public void Dispose()
{
GC.SuppressFinalize(this);
keyboardMonitor?.Dispose();
+ etwTrace?.Dispose();
}
private void Application_Startup(object sender, StartupEventArgs e)
diff --git a/src/modules/PowerOCR/PowerOCRModuleInterface/dllmain.cpp b/src/modules/PowerOCR/PowerOCRModuleInterface/dllmain.cpp
index 1eebf010ee..b9695d6d35 100644
--- a/src/modules/PowerOCR/PowerOCRModuleInterface/dllmain.cpp
+++ b/src/modules/PowerOCR/PowerOCRModuleInterface/dllmain.cpp
@@ -69,6 +69,8 @@ private:
// Handle to event used to invoke PowerOCR
HANDLE m_hInvokeEvent;
+ // Handle to event used to terminate PowerOCR
+ HANDLE m_hTerminateEvent;
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
@@ -160,6 +162,7 @@ public:
app_key = PowerOcrConstants::ModuleKey;
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "TextExtractor");
m_hInvokeEvent = CreateDefaultEvent(CommonSharedConstants::SHOW_POWEROCR_SHARED_EVENT);
+ m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_POWEROCR_SHARED_EVENT);
init_settings();
}
@@ -249,6 +252,8 @@ public:
if (m_enabled)
{
ResetEvent(m_hInvokeEvent);
+ SetEvent(m_hTerminateEvent);
+ WaitForSingleObject(m_hProcess, 1500);
TerminateProcess(m_hProcess, 1);
}
diff --git a/src/modules/PowerOCR/PowerOCRModuleInterface/pch.h b/src/modules/PowerOCR/PowerOCRModuleInterface/pch.h
index eddac0fdc1..329705f63b 100644
--- a/src/modules/PowerOCR/PowerOCRModuleInterface/pch.h
+++ b/src/modules/PowerOCR/PowerOCRModuleInterface/pch.h
@@ -2,6 +2,5 @@
#include
#include
#include
-#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/PowerOCR/PowerOCRModuleInterface/trace.cpp b/src/modules/PowerOCR/PowerOCRModuleInterface/trace.cpp
index 6751270726..979619b915 100644
--- a/src/modules/PowerOCR/PowerOCRModuleInterface/trace.cpp
+++ b/src/modules/PowerOCR/PowerOCRModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has PowerOCR enabled or disabled
void Trace::EnablePowerOCR(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"PowerOCR_EnablePowerOCR",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/PowerOCR/PowerOCRModuleInterface/trace.h b/src/modules/PowerOCR/PowerOCRModuleInterface/trace.h
index a68576c302..b8e428994e 100644
--- a/src/modules/PowerOCR/PowerOCRModuleInterface/trace.h
+++ b/src/modules/PowerOCR/PowerOCRModuleInterface/trace.h
@@ -1,10 +1,10 @@
#pragma once
-class Trace
+
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
// Log if the user has PowerOCR enabled or disabled
static void EnablePowerOCR(const bool enabled) noexcept;
};
diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj
index 68ef97516d..045be94f2b 100644
--- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj
+++ b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj
@@ -158,6 +158,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/ShortcutGuide/ShortcutGuide/main.cpp b/src/modules/ShortcutGuide/ShortcutGuide/main.cpp
index 4cd5d78a72..713446403b 100644
--- a/src/modules/ShortcutGuide/ShortcutGuide/main.cpp
+++ b/src/modules/ShortcutGuide/ShortcutGuide/main.cpp
@@ -9,6 +9,8 @@
#include
#include
+#include
+
#include "shortcut_guide.h"
#include "target_state.h"
#include "ShortcutGuideConstants.h"
@@ -48,6 +50,9 @@ int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInst
winrt::init_apartment();
LoggerHelpers::init_logger(ShortcutGuideConstants::ModuleKey, L"ShortcutGuide", LogSettings::shortcutGuideLoggerName);
+ Shared::Trace::ETWTrace trace;
+ trace.UpdateState(true);
+
if (powertoys_gpo::getConfiguredShortcutGuideEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)
{
Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
@@ -132,6 +137,8 @@ int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInst
window.ShowWindow();
run_message_loop();
+
+ trace.Flush();
Trace::UnregisterProvider();
return 0;
}
diff --git a/src/modules/ShortcutGuide/ShortcutGuide/pch.h b/src/modules/ShortcutGuide/ShortcutGuide/pch.h
index 7cfa22c4fa..9ec2bbcb41 100644
--- a/src/modules/ShortcutGuide/ShortcutGuide/pch.h
+++ b/src/modules/ShortcutGuide/ShortcutGuide/pch.h
@@ -25,6 +25,5 @@
#include
#include
#include
-#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp b/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp
index b68e7bbcad..f2a414d6ac 100644
--- a/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp
+++ b/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,19 +10,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::SendGuideSession(const __int64 duration_ms, const wchar_t* close_type) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ShortcutGuide_GuideSession",
TraceLoggingInt64(duration_ms, "DurationInMs"),
@@ -32,7 +24,7 @@ void Trace::SendGuideSession(const __int64 duration_ms, const wchar_t* close_typ
void Trace::SendSettings(ShortcutGuideSettings settings) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ShortcutGuide_Settings",
TraceLoggingWideString(settings.hotkey.c_str(), "Hotkey"),
diff --git a/src/modules/ShortcutGuide/ShortcutGuide/trace.h b/src/modules/ShortcutGuide/ShortcutGuide/trace.h
index 97f9d75bc8..a3446a8570 100644
--- a/src/modules/ShortcutGuide/ShortcutGuide/trace.h
+++ b/src/modules/ShortcutGuide/ShortcutGuide/trace.h
@@ -1,11 +1,11 @@
#pragma once
#include "ShortcutGuideSettings.h"
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
static void SendGuideSession(const __int64 duration_ms, const wchar_t* close_type) noexcept;
static void SendSettings(ShortcutGuideSettings settings) noexcept;
};
diff --git a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/pch.h b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/pch.h
index 799a9214a1..37cb34a58a 100644
--- a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/pch.h
+++ b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/pch.h
@@ -2,7 +2,6 @@
#define NOMINMAX
#include
#include
-#include
#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/Workspaces/WorkspacesEditor/App.xaml.cs b/src/modules/Workspaces/WorkspacesEditor/App.xaml.cs
index df86a35ed9..669230b744 100644
--- a/src/modules/Workspaces/WorkspacesEditor/App.xaml.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/App.xaml.cs
@@ -9,6 +9,7 @@ using System.Windows;
using Common.UI;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
using WorkspacesEditor.Utils;
using WorkspacesEditor.ViewModels;
@@ -31,6 +32,8 @@ namespace WorkspacesEditor
private bool _isDisposed;
+ private ETWTrace etwTrace = new ETWTrace();
+
public App()
{
WorkspacesEditorIO = new WorkspacesEditorIO();
@@ -135,6 +138,7 @@ namespace WorkspacesEditor
{
ThemeManager?.Dispose();
_instanceMutex?.Dispose();
+ etwTrace?.Dispose();
}
_isDisposed = true;
diff --git a/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml.cs b/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml.cs
index 63bcb15016..a0a7f96a06 100644
--- a/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml.cs
@@ -8,6 +8,7 @@ using System.Windows;
using System.Windows.Interop;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
using WorkspacesEditor.Utils;
using WorkspacesEditor.ViewModels;
diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs b/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs
index 294d59854d..02681dd841 100644
--- a/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs
@@ -360,38 +360,7 @@ namespace WorkspacesEditor.Models
{
if (_monitorSetup == null)
{
- _monitorSetup = Parent.Monitors.Where(x => x.MonitorNumber == MonitorNumber).FirstOrDefault();
- if (_monitorSetup == null)
- {
- // monitors changed: try to determine monitor id based on middle point
- int middleX = Position.X + (Position.Width / 2);
- int middleY = Position.Y + (Position.Height / 2);
- var monitorCandidate = Parent.Monitors.Where(x =>
- (x.MonitorDpiUnawareBounds.Left < middleX) &&
- (x.MonitorDpiUnawareBounds.Right > middleX) &&
- (x.MonitorDpiUnawareBounds.Top < middleY) &&
- (x.MonitorDpiUnawareBounds.Bottom > middleY)).FirstOrDefault();
- if (monitorCandidate != null)
- {
- _monitorSetup = monitorCandidate;
- MonitorNumber = monitorCandidate.MonitorNumber;
- }
- else
- {
- // monitors and even the app's area unknown, set the main monitor (which is closer to (0,0)) as the app's monitor
- monitorCandidate = Parent.Monitors.OrderBy(x => Math.Abs(x.MonitorDpiUnawareBounds.Left) + Math.Abs(x.MonitorDpiUnawareBounds.Top)).FirstOrDefault();
- if (monitorCandidate != null)
- {
- _monitorSetup = monitorCandidate;
- MonitorNumber = monitorCandidate.MonitorNumber;
- }
- else
- {
- // no monitors defined at all.
- Logger.LogError($"Wrong workspace setup. No monitors defined for the workspace: {Parent.Name}.");
- }
- }
- }
+ _monitorSetup = Parent.GetMonitorForApp(this);
}
return _monitorSetup;
diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs b/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs
index 07d7ad40a1..e65853f1e3 100644
--- a/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs
@@ -374,5 +374,44 @@ namespace WorkspacesEditor.Models
app.IsExpanded = false;
}
}
+
+ internal MonitorSetup GetMonitorForApp(Application app)
+ {
+ var monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
+ if (monitorSetup == null)
+ {
+ // monitors changed: try to determine monitor id based on middle point
+ int middleX = app.Position.X + (app.Position.Width / 2);
+ int middleY = app.Position.Y + (app.Position.Height / 2);
+ var monitorCandidate = Monitors.Where(x =>
+ (x.MonitorDpiUnawareBounds.Left < middleX) &&
+ (x.MonitorDpiUnawareBounds.Right > middleX) &&
+ (x.MonitorDpiUnawareBounds.Top < middleY) &&
+ (x.MonitorDpiUnawareBounds.Bottom > middleY)).FirstOrDefault();
+ if (monitorCandidate != null)
+ {
+ app.MonitorNumber = monitorCandidate.MonitorNumber;
+ return monitorCandidate;
+ }
+ else
+ {
+ // monitors and even the app's area unknown, set the main monitor (which is closer to (0,0)) as the app's monitor
+ monitorCandidate = Monitors.OrderBy(x => Math.Abs(x.MonitorDpiUnawareBounds.Left) + Math.Abs(x.MonitorDpiUnawareBounds.Top)).FirstOrDefault();
+ if (monitorCandidate != null)
+ {
+ app.MonitorNumber = monitorCandidate.MonitorNumber;
+ return monitorCandidate;
+ }
+ else
+ {
+ // no monitors defined at all.
+ Logger.LogError($"Wrong workspace setup. No monitors defined for the workspace: {Name}.");
+ return null;
+ }
+ }
+ }
+
+ return monitorSetup;
+ }
}
}
diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs
index 217a942ba5..45da7a6c2c 100644
--- a/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs
@@ -54,7 +54,13 @@ namespace WorkspacesEditor.Utils
if (app.Maximized)
{
Project project = app.Parent;
- var monitor = project.Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
+ var monitor = project.GetMonitorForApp(app);
+ if (monitor == null)
+ {
+ // unrealistic case, there are no monitors at all in the workspace, use original rect
+ return new Rectangle(TransformX(app.ScaledPosition.X), TransformY(app.ScaledPosition.Y), Scaled(app.ScaledPosition.Width), Scaled(app.ScaledPosition.Height));
+ }
+
return new Rectangle(TransformX(monitor.MonitorDpiAwareBounds.Left), TransformY(monitor.MonitorDpiAwareBounds.Top), Scaled(monitor.MonitorDpiAwareBounds.Width), Scaled(monitor.MonitorDpiAwareBounds.Height));
}
else
diff --git a/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs b/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs
index 3f57532818..aae85161cb 100644
--- a/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs
+++ b/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs
@@ -398,6 +398,11 @@ namespace WorkspacesEditor.ViewModels
public async void LaunchProject(Project project, bool exitAfterLaunch = false)
{
+ if (project == null)
+ {
+ return;
+ }
+
await Task.Run(() => RunLauncher(project.Id, InvokePoint.EditorButton));
if (_workspacesEditorIO.ParseWorkspaces(this).Result == true)
{
diff --git a/src/modules/Workspaces/WorkspacesLauncher/WorkspacesLauncher.vcxproj b/src/modules/Workspaces/WorkspacesLauncher/WorkspacesLauncher.vcxproj
index 8ff482677c..9d4fc4bcab 100644
--- a/src/modules/Workspaces/WorkspacesLauncher/WorkspacesLauncher.vcxproj
+++ b/src/modules/Workspaces/WorkspacesLauncher/WorkspacesLauncher.vcxproj
@@ -155,6 +155,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{b31fcc55-b5a4-4ea7-b414-2dceae6af332}
diff --git a/src/modules/Workspaces/WorkspacesLauncher/main.cpp b/src/modules/Workspaces/WorkspacesLauncher/main.cpp
index 3e7c8c7db1..09f63785b1 100644
--- a/src/modules/Workspaces/WorkspacesLauncher/main.cpp
+++ b/src/modules/Workspaces/WorkspacesLauncher/main.cpp
@@ -7,6 +7,8 @@
#include
#include
+#include
+
#include
#include
@@ -14,6 +16,7 @@
#include
#include
+#include
const std::wstring moduleName = L"Workspaces\\WorkspacesLauncher";
const std::wstring internalPath = L"";
@@ -22,7 +25,12 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_WorkspacesLauncher_Ins
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cmdShow)
{
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::workspacesLauncherLoggerName);
- InitUnhandledExceptionHandler();
+ InitUnhandledExceptionHandler();
+
+ Trace::Workspaces::RegisterProvider();
+
+ Shared::Trace::ETWTrace trace{};
+ trace.UpdateState(true);
if (powertoys_gpo::getConfiguredWorkspacesEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)
{
@@ -60,7 +68,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
GetModuleFileNameW(nullptr, exe_path.get(), exe_path_size);
const auto modulePath = get_module_folderpath();
-
+
std::string cmdLineStr(cmdline);
std::wstring cmdLineWStr(cmdLineStr.begin(), cmdLineStr.end());
@@ -78,7 +86,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
}
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
-
+
Logger::trace(L"Invoke point: {}", cmdArgs.invokePoint);
// read workspaces
@@ -105,12 +113,12 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
formattedMessage = fmt::format(GET_RESOURCE_STRING(IDS_INCORRECT_FILE_ERROR), file);
break;
}
-
+
MessageBox(NULL, formattedMessage.c_str(), GET_RESOURCE_STRING(IDS_WORKSPACES).c_str(), MB_ICONERROR | MB_OK);
return 1;
}
}
-
+
if (projectToLaunch.id.empty())
{
auto file = WorkspacesData::WorkspacesFile();
@@ -177,7 +185,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
}
}
- // update the file before launching, so WorkspacesWindowArranger and WorkspacesLauncherUI could get updated app paths
+ // update the file before launching, so WorkspacesWindowArranger and WorkspacesLauncherUI could get updated app paths
if (updatedApps || updatedIds)
{
for (int i = 0; i < workspaces.size(); i++)
@@ -193,7 +201,14 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
}
// launch
- Launcher launcher(projectToLaunch, workspaces, cmdArgs.invokePoint);
+ {
+ Launcher launcher(projectToLaunch, workspaces, cmdArgs.invokePoint);
+ }
+
+ trace.Flush();
+ trace.UpdateState(false);
+
+ Trace::Workspaces::UnregisterProvider();
Logger::trace("Finished");
CoUninitialize();
diff --git a/src/modules/Workspaces/WorkspacesLauncherUI/App.xaml.cs b/src/modules/Workspaces/WorkspacesLauncherUI/App.xaml.cs
index 64686fc139..3359c001d5 100644
--- a/src/modules/Workspaces/WorkspacesLauncherUI/App.xaml.cs
+++ b/src/modules/Workspaces/WorkspacesLauncherUI/App.xaml.cs
@@ -6,6 +6,7 @@ using System;
using System.Globalization;
using System.Threading;
using System.Windows;
+
using Common.UI;
using ManagedCommon;
using PowerToys.Interop;
diff --git a/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchData.cs b/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchData.cs
index dc19b86647..6e9ad24379 100644
--- a/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchData.cs
+++ b/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchData.cs
@@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
+
using Workspaces.Data;
+
using static WorkspacesLauncherUI.Data.AppLaunchData;
using static WorkspacesLauncherUI.Data.AppLaunchInfosData;
diff --git a/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchInfoData.cs b/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchInfoData.cs
index aa64510ba9..c01ffaba8c 100644
--- a/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchInfoData.cs
+++ b/src/modules/Workspaces/WorkspacesLauncherUI/Data/AppLaunchInfoData.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
+
using Workspaces.Data;
using static WorkspacesLauncherUI.Data.AppLaunchInfoData;
diff --git a/src/modules/Workspaces/WorkspacesLauncherUI/Models/AppLaunching.cs b/src/modules/Workspaces/WorkspacesLauncherUI/Models/AppLaunching.cs
index f3878a3847..073ee9c864 100644
--- a/src/modules/Workspaces/WorkspacesLauncherUI/Models/AppLaunching.cs
+++ b/src/modules/Workspaces/WorkspacesLauncherUI/Models/AppLaunching.cs
@@ -13,6 +13,7 @@ using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+
using ManagedCommon;
using Windows.Management.Deployment;
using WorkspacesLauncherUI.Data;
diff --git a/src/modules/Workspaces/WorkspacesLauncherUI/ViewModels/MainViewModel.cs b/src/modules/Workspaces/WorkspacesLauncherUI/ViewModels/MainViewModel.cs
index 7002c9ef05..103b08d6f7 100644
--- a/src/modules/Workspaces/WorkspacesLauncherUI/ViewModels/MainViewModel.cs
+++ b/src/modules/Workspaces/WorkspacesLauncherUI/ViewModels/MainViewModel.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
+
using ManagedCommon;
using WorkspacesLauncherUI.Data;
using WorkspacesLauncherUI.Models;
diff --git a/src/modules/Workspaces/WorkspacesLib/trace.cpp b/src/modules/Workspaces/WorkspacesLib/trace.cpp
index 2802175058..5b80fb2601 100644
--- a/src/modules/Workspaces/WorkspacesLib/trace.cpp
+++ b/src/modules/Workspaces/WorkspacesLib/trace.cpp
@@ -13,19 +13,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::Workspaces::Enable(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Workspaces_Enable",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -77,7 +67,7 @@ void Trace::Workspaces::Launch(bool success,
errorStr += exeName + L":" + errorMessage + L"; ";
}
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Workspaces_LaunchEvent",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/Workspaces/WorkspacesLib/trace.h b/src/modules/Workspaces/WorkspacesLib/trace.h
index d5569ba0b0..addb4bf245 100644
--- a/src/modules/Workspaces/WorkspacesLib/trace.h
+++ b/src/modules/Workspaces/WorkspacesLib/trace.h
@@ -5,13 +5,12 @@
#include
#include
+#include
+
class Trace
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
- class Workspaces
+ class Workspaces : public telemetry::TraceBase
{
public:
static void Enable(bool enabled) noexcept;
diff --git a/src/modules/Workspaces/WorkspacesModuleInterface/dllmain.cpp b/src/modules/Workspaces/WorkspacesModuleInterface/dllmain.cpp
index 21ccd19261..90c898fc5f 100644
--- a/src/modules/Workspaces/WorkspacesModuleInterface/dllmain.cpp
+++ b/src/modules/Workspaces/WorkspacesModuleInterface/dllmain.cpp
@@ -38,7 +38,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
- Trace::RegisterProvider();
+ Trace::Workspaces::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
@@ -46,7 +46,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
break;
case DLL_PROCESS_DETACH:
- Trace::UnregisterProvider();
+ Trace::Workspaces::UnregisterProvider();
break;
}
return TRUE;
diff --git a/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.cpp b/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.cpp
index 4642a5952e..519f2ccfa8 100644
--- a/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.cpp
+++ b/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.cpp
@@ -168,7 +168,7 @@ namespace SnapshotUtils
return false;
}
- std::vector GetApps(const std::function getMonitorNumberFromWindowHandle)
+ std::vector GetApps(const std::function getMonitorNumberFromWindowHandle, const std::function getMonitorRect)
{
std::vector apps{};
@@ -249,6 +249,19 @@ namespace SnapshotUtils
continue;
}
+ bool isMinimized = WindowUtils::IsMinimized(window);
+ unsigned int monitorNumber = getMonitorNumberFromWindowHandle(window);
+
+ if (isMinimized)
+ {
+ // set the screen area as position, the values we get for the minimized windows are out of the screens' area
+ WorkspacesData::WorkspacesProject::Monitor::MonitorRect monitorRect = getMonitorRect(monitorNumber);
+ rect.left = monitorRect.left;
+ rect.top = monitorRect.top;
+ rect.right = monitorRect.left + monitorRect.width;
+ rect.bottom = monitorRect.top + monitorRect.height;
+ }
+
WorkspacesData::WorkspacesProject::Application app{
.name = data.value().name,
.title = title,
@@ -258,7 +271,7 @@ namespace SnapshotUtils
.commandLineArgs = L"", // GetCommandLineArgs(pid, wbemHelper),
.isElevated = IsProcessElevated(pid),
.canLaunchElevated = data.value().canLaunchElevated,
- .isMinimized = WindowUtils::IsMinimized(window),
+ .isMinimized = isMinimized,
.isMaximized = WindowUtils::IsMaximized(window),
.position = WorkspacesData::WorkspacesProject::Application::Position{
.x = rect.left,
@@ -266,7 +279,7 @@ namespace SnapshotUtils
.width = rect.right - rect.left,
.height = rect.bottom - rect.top,
},
- .monitor = getMonitorNumberFromWindowHandle(window),
+ .monitor = monitorNumber,
};
apps.push_back(app);
diff --git a/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.h b/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.h
index 1009c60d3c..df95bbadf3 100644
--- a/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.h
+++ b/src/modules/Workspaces/WorkspacesSnapshotTool/SnapshotUtils.h
@@ -4,5 +4,5 @@
namespace SnapshotUtils
{
- std::vector GetApps(const std::function getMonitorNumberFromWindowHandle);
+ std::vector GetApps(const std::function getMonitorNumberFromWindowHandle, const std::function getMonitorRect);
};
diff --git a/src/modules/Workspaces/WorkspacesSnapshotTool/main.cpp b/src/modules/Workspaces/WorkspacesSnapshotTool/main.cpp
index b736ce238e..8a99ea6ef5 100644
--- a/src/modules/Workspaces/WorkspacesSnapshotTool/main.cpp
+++ b/src/modules/Workspaces/WorkspacesSnapshotTool/main.cpp
@@ -65,7 +65,15 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdLine, int cm
}
return monitorNumber;
- });
+ }, [&](unsigned int monitorId) -> WorkspacesData::WorkspacesProject::Monitor::MonitorRect {
+ for (const auto& monitor : project.monitors)
+ {
+ if (monitor.number == monitorId)
+ {
+ return monitor.monitorRectDpiUnaware;
+ }
+ }
+ return project.monitors[0].monitorRectDpiUnaware; });
JsonUtils::Write(WorkspacesData::TempWorkspacesFile(), project);
Logger::trace(L"WorkspacesProject {}:{} created", project.name, project.id);
diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.cpp b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.cpp
index b9ec910c62..491a0bdf42 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.cpp
+++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.cpp
@@ -32,10 +32,11 @@ bool isExcluded(HWND window)
return check_excluded_app(window, processPath, AlwaysOnTopSettings::settings().excludedApps);
}
-AlwaysOnTop::AlwaysOnTop(bool useLLKH) :
+AlwaysOnTop::AlwaysOnTop(bool useLLKH, DWORD mainThreadId) :
SettingsObserver({SettingId::FrameEnabled, SettingId::Hotkey, SettingId::ExcludeApps}),
m_hinstance(reinterpret_cast(&__ImageBase)),
- m_useCentralizedLLKH(useLLKH)
+ m_useCentralizedLLKH(useLLKH),
+ m_mainThreadId(mainThreadId)
{
s_instance = this;
DPIAware::EnableDPIAwarenessForThisProcess();
@@ -282,6 +283,7 @@ void AlwaysOnTop::RegisterLLKH()
}
m_hPinEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::ALWAYS_ON_TOP_PIN_EVENT);
+ m_hTerminateEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::ALWAYS_ON_TOP_TERMINATE_EVENT);
if (!m_hPinEvent)
{
@@ -289,11 +291,20 @@ void AlwaysOnTop::RegisterLLKH()
return;
}
- m_thread = std::thread([this]() {
+ if (!m_hTerminateEvent)
+ {
+ Logger::warn(L"Failed to create terminateEvent. {}", get_last_error_or_default(GetLastError()));
+ return;
+ }
+
+ HANDLE handles[2] = { m_hPinEvent,
+ m_hTerminateEvent };
+
+ m_thread = std::thread([this, handles]() {
MSG msg;
while (m_running)
{
- DWORD dwEvt = MsgWaitForMultipleObjects(1, &m_hPinEvent, false, INFINITE, QS_ALLINPUT);
+ DWORD dwEvt = MsgWaitForMultipleObjects(2, handles, false, INFINITE, QS_ALLINPUT);
if (!m_running)
{
break;
@@ -307,6 +318,9 @@ void AlwaysOnTop::RegisterLLKH()
}
break;
case WAIT_OBJECT_0 + 1:
+ PostThreadMessage(m_mainThreadId, WM_QUIT, 0, 0);
+ break;
+ case WAIT_OBJECT_0 + 2:
if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.h b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.h
index dc41a12d67..da14d508b2 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.h
+++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.h
@@ -13,7 +13,7 @@
class AlwaysOnTop : public SettingsObserver
{
public:
- AlwaysOnTop(bool useLLKH);
+ AlwaysOnTop(bool useLLKH, DWORD mainThreadId);
~AlwaysOnTop();
protected:
@@ -48,6 +48,8 @@ private:
HINSTANCE m_hinstance;
std::map> m_topmostWindows{};
HANDLE m_hPinEvent;
+ HANDLE m_hTerminateEvent;
+ DWORD m_mainThreadId;
std::thread m_thread;
const bool m_useCentralizedLLKH;
bool m_running = true;
diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj
index 95e051238e..bf3e5c6851 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj
+++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj
@@ -170,6 +170,9 @@
{1d5be09d-78c0-4fd7-af00-ae7c1af7c525}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
diff --git a/src/modules/alwaysontop/AlwaysOnTop/main.cpp b/src/modules/alwaysontop/AlwaysOnTop/main.cpp
index 8b7d901c7d..417525a852 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/main.cpp
+++ b/src/modules/alwaysontop/AlwaysOnTop/main.cpp
@@ -1,11 +1,12 @@
#include "pch.h"
+#include
#include
#include
#include
#include
-#include
+#include
#include
#include
@@ -17,6 +18,9 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_AlwaysOnTop_InstanceMu
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
{
+ Shared::Trace::ETWTrace trace;
+ trace.UpdateState(true);
+
winrt::init_apartment();
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::alwaysOnTopLoggerName);
@@ -39,10 +43,11 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
return 0;
}
+ auto mainThreadId = GetCurrentThreadId();
+
std::wstring pid = std::wstring(lpCmdLine);
if (!pid.empty())
{
- auto mainThreadId = GetCurrentThreadId();
ProcessWaiter::OnProcessTerminate(pid, [mainThreadId](int err) {
if (err != ERROR_SUCCESS)
{
@@ -58,13 +63,15 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
});
}
- Trace::RegisterProvider();
+ Trace::AlwaysOnTop::RegisterProvider();
- AlwaysOnTop app(!pid.empty());
+ AlwaysOnTop app(!pid.empty(), mainThreadId);
run_message_loop();
- Trace::UnregisterProvider();
-
+ Trace::AlwaysOnTop::UnregisterProvider();
+
+ trace.Flush();
+
return 0;
}
diff --git a/src/modules/alwaysontop/AlwaysOnTop/pch.h b/src/modules/alwaysontop/AlwaysOnTop/pch.h
index 848c90fea2..d3a92e228f 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/pch.h
+++ b/src/modules/alwaysontop/AlwaysOnTop/pch.h
@@ -4,7 +4,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/src/modules/alwaysontop/AlwaysOnTop/trace.cpp b/src/modules/alwaysontop/AlwaysOnTop/trace.cpp
index ae32849bbf..fb3739f4df 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/trace.cpp
+++ b/src/modules/alwaysontop/AlwaysOnTop/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
// Telemetry strings should not be localized.
#define LoggingProviderKey "Microsoft.PowerToys"
@@ -16,19 +18,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::AlwaysOnTop::Enable(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventEnableAlwaysOnTopKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -38,7 +30,7 @@ void Trace::AlwaysOnTop::Enable(bool enabled) noexcept
void Trace::AlwaysOnTop::PinWindow() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventPinWindowKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -47,7 +39,7 @@ void Trace::AlwaysOnTop::PinWindow() noexcept
void Trace::AlwaysOnTop::UnpinWindow() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventUnpinWindowKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/alwaysontop/AlwaysOnTop/trace.h b/src/modules/alwaysontop/AlwaysOnTop/trace.h
index 23c88d3c01..05ac601101 100644
--- a/src/modules/alwaysontop/AlwaysOnTop/trace.h
+++ b/src/modules/alwaysontop/AlwaysOnTop/trace.h
@@ -1,12 +1,11 @@
#pragma once
+#include
+
class Trace
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
- class AlwaysOnTop
+ class AlwaysOnTop : public telemetry::TraceBase
{
public:
static void Enable(bool enabled) noexcept;
diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp
index 83158813c6..84cf9ed949 100644
--- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp
+++ b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp
@@ -35,7 +35,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
- Trace::RegisterProvider();
+ Trace::AlwaysOnTop::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
@@ -43,7 +43,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
break;
case DLL_PROCESS_DETACH:
- Trace::UnregisterProvider();
+ Trace::AlwaysOnTop::UnregisterProvider();
break;
}
return TRUE;
@@ -174,6 +174,7 @@ public:
app_name = L"AlwaysOnTop"; //TODO: localize
app_key = NonLocalizable::ModuleKey;
m_hPinEvent = CreateDefaultEvent(CommonSharedConstants::ALWAYS_ON_TOP_PIN_EVENT);
+ m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::ALWAYS_ON_TOP_TERMINATE_EVENT);
init_settings();
}
@@ -221,6 +222,12 @@ private:
Trace::AlwaysOnTop::Enable(false);
}
+ SetEvent(m_hTerminateEvent);
+
+ // Wait for 1.5 seconds for the process to end correctly and stop etw tracer
+ WaitForSingleObject(m_hProcess, 1500);
+
+ // If process is still running, terminate it
if (m_hProcess)
{
TerminateProcess(m_hProcess, 0);
@@ -294,6 +301,7 @@ private:
// Handle to event used to pin/unpin windows
HANDLE m_hPinEvent;
+ HANDLE m_hTerminateEvent;
};
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h
index d70de4e4d4..9dc1f70972 100644
--- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h
+++ b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h
@@ -5,7 +5,5 @@
#include
#include
#include
-#include
-#include
#include
#include
diff --git a/src/modules/awake/Awake/Core/Manager.cs b/src/modules/awake/Awake/Core/Manager.cs
index f237250635..ba69f9c8df 100644
--- a/src/modules/awake/Awake/Core/Manager.cs
+++ b/src/modules/awake/Awake/Core/Manager.cs
@@ -14,6 +14,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
+
using Awake.Core.Models;
using Awake.Core.Native;
using Awake.Properties;
diff --git a/src/modules/awake/Awake/Core/Threading/SingleThreadSynchronizationContext.cs b/src/modules/awake/Awake/Core/Threading/SingleThreadSynchronizationContext.cs
index 04c28dfd34..e45c13bad0 100644
--- a/src/modules/awake/Awake/Core/Threading/SingleThreadSynchronizationContext.cs
+++ b/src/modules/awake/Awake/Core/Threading/SingleThreadSynchronizationContext.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
+
using ManagedCommon;
namespace Awake.Core.Threading
diff --git a/src/modules/awake/Awake/Core/TrayHelper.cs b/src/modules/awake/Awake/Core/TrayHelper.cs
index 0545f97a8f..8568f80cfa 100644
--- a/src/modules/awake/Awake/Core/TrayHelper.cs
+++ b/src/modules/awake/Awake/Core/TrayHelper.cs
@@ -9,6 +9,7 @@ using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
+
using Awake.Core.Models;
using Awake.Core.Native;
using Awake.Core.Threading;
diff --git a/src/modules/awake/Awake/Program.cs b/src/modules/awake/Awake/Program.cs
index d1311ef51f..08995479d4 100644
--- a/src/modules/awake/Awake/Program.cs
+++ b/src/modules/awake/Awake/Program.cs
@@ -15,12 +15,14 @@ using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
+
using Awake.Core;
using Awake.Core.Models;
using Awake.Core.Native;
using Awake.Properties;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Telemetry;
namespace Awake
{
@@ -29,6 +31,7 @@ namespace Awake
private static Mutex? _mutex;
private static FileSystemWatcher? _watcher;
private static SettingsUtils? _settingsUtils;
+ private static ETWTrace _etwTrace = new ETWTrace();
private static bool _startedFromPowerToys;
@@ -176,6 +179,7 @@ namespace Awake
private static void Exit(string message, int exitCode)
{
+ _etwTrace?.Dispose();
Logger.LogInfo(message);
Manager.CompleteExit(exitCode);
}
diff --git a/src/modules/awake/AwakeModuleInterface/pch.h b/src/modules/awake/AwakeModuleInterface/pch.h
index eddac0fdc1..329705f63b 100644
--- a/src/modules/awake/AwakeModuleInterface/pch.h
+++ b/src/modules/awake/AwakeModuleInterface/pch.h
@@ -2,6 +2,5 @@
#include
#include
#include
-#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/awake/AwakeModuleInterface/trace.cpp b/src/modules/awake/AwakeModuleInterface/trace.cpp
index fe90aa2658..971084e4ab 100644
--- a/src/modules/awake/AwakeModuleInterface/trace.cpp
+++ b/src/modules/awake/AwakeModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has Awake enabled or disabled
void Trace::EnableAwake(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"Awake_EnableAwake",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/awake/AwakeModuleInterface/trace.h b/src/modules/awake/AwakeModuleInterface/trace.h
index 40a903b98a..95a9a4e46e 100644
--- a/src/modules/awake/AwakeModuleInterface/trace.h
+++ b/src/modules/awake/AwakeModuleInterface/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
// Log if the user has Awake enabled or disabled
static void EnableAwake(const bool enabled) noexcept;
};
diff --git a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
index 96a774ab2a..8706bb4cf9 100644
--- a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
+++ b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
@@ -11,6 +11,4 @@
// Windows Header Files
#include
-#include
-
#endif //PCH_H
diff --git a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
index 255c46ea99..c136909f32 100644
--- a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
+++ b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if the user has CmdNotFound enabled or disabled
void Trace::EnableCmdNotFoundGpo(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"CmdNotFound_EnableCmdNotFound",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
index 4294c510a6..6fb84c5f10 100644
--- a/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
+++ b/src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
// Log if the user has CmdNotFound enabled or disabled
static void EnableCmdNotFoundGpo(const bool enabled) noexcept;
};
diff --git a/src/modules/colorPicker/ColorPicker/dllmain.cpp b/src/modules/colorPicker/ColorPicker/dllmain.cpp
index ae235a6686..cf7ebec6a0 100644
--- a/src/modules/colorPicker/ColorPicker/dllmain.cpp
+++ b/src/modules/colorPicker/ColorPicker/dllmain.cpp
@@ -67,6 +67,8 @@ private:
// Handle to event used to invoke ColorPicker
HANDLE m_hInvokeEvent;
+ HANDLE m_hAppTerminateEvent;
+
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -158,6 +160,7 @@ public:
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "ColorPicker");
send_telemetry_event = CreateDefaultEvent(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT);
m_hInvokeEvent = CreateDefaultEvent(CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT);
+ m_hAppTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_COLOR_PICKER_SHARED_EVENT);
init_settings();
}
@@ -249,6 +252,10 @@ public:
{
ResetEvent(send_telemetry_event);
ResetEvent(m_hInvokeEvent);
+
+ SetEvent(m_hAppTerminateEvent);
+ WaitForSingleObject(m_hProcess, 1500);
+
TerminateProcess(m_hProcess, 1);
}
diff --git a/src/modules/colorPicker/ColorPicker/pch.h b/src/modules/colorPicker/ColorPicker/pch.h
index eddac0fdc1..329705f63b 100644
--- a/src/modules/colorPicker/ColorPicker/pch.h
+++ b/src/modules/colorPicker/ColorPicker/pch.h
@@ -2,6 +2,5 @@
#include
#include
#include
-#include
#include
#include
\ No newline at end of file
diff --git a/src/modules/colorPicker/ColorPicker/trace.cpp b/src/modules/colorPicker/ColorPicker/trace.cpp
index 285cea034e..61ddb9b3e1 100644
--- a/src/modules/colorPicker/ColorPicker/trace.cpp
+++ b/src/modules/colorPicker/ColorPicker/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log if ColorPicker is enabled or disabled
void Trace::EnableColorPicker(const bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ColorPicker_EnableColorPicker",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/colorPicker/ColorPicker/trace.h b/src/modules/colorPicker/ColorPicker/trace.h
index b133664008..594239cf34 100644
--- a/src/modules/colorPicker/ColorPicker/trace.h
+++ b/src/modules/colorPicker/ColorPicker/trace.h
@@ -1,10 +1,10 @@
#pragma once
-class Trace
+
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider();
- static void UnregisterProvider();
-
// Log if ColorPicker is enabled or disabled
static void EnableColorPicker(const bool enabled) noexcept;
diff --git a/src/modules/colorPicker/ColorPickerUI/App.xaml.cs b/src/modules/colorPicker/ColorPickerUI/App.xaml.cs
index 98646583be..0621fbc4b9 100644
--- a/src/modules/colorPicker/ColorPickerUI/App.xaml.cs
+++ b/src/modules/colorPicker/ColorPickerUI/App.xaml.cs
@@ -10,6 +10,7 @@ using System.Windows;
using ColorPicker.Mouse;
using ManagedCommon;
+using Microsoft.PowerToys.Telemetry;
namespace ColorPickerUI
{
@@ -18,6 +19,8 @@ namespace ColorPickerUI
///
public partial class App : Application, IDisposable
{
+ public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
+
private Mutex _instanceMutex;
private static string[] _args;
private int _powerToysRunnerPid;
@@ -96,6 +99,7 @@ namespace ColorPickerUI
if (disposing)
{
_instanceMutex?.Dispose();
+ EtwTrace?.Dispose();
}
disposedValue = true;
diff --git a/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs b/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs
index c135f82362..eb94d86d1e 100644
--- a/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs
+++ b/src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Windows;
using ColorPicker.Helpers;
using Common.UI;
diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
index 63772b7963..518f253456 100644
--- a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
+++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
@@ -57,6 +57,12 @@ namespace ColorPicker.ViewModels
_userSettings = userSettings;
_keyboardMonitor = keyboardMonitor;
+ NativeEventWaiter.WaitForEventLoop(
+ Constants.TerminateColorPickerSharedEvent(),
+ Application.Current.Shutdown,
+ Application.Current.Dispatcher,
+ exitToken);
+
NativeEventWaiter.WaitForEventLoop(
Constants.ShowColorPickerSharedEvent(),
_appStateHandler.StartUserSession,
diff --git a/src/modules/fancyzones/FancyZones/FancyZones.vcxproj b/src/modules/fancyzones/FancyZones/FancyZones.vcxproj
index d61eeb60fd..b54ee19e34 100644
--- a/src/modules/fancyzones/FancyZones/FancyZones.vcxproj
+++ b/src/modules/fancyzones/FancyZones/FancyZones.vcxproj
@@ -146,6 +146,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{f9c68edf-ac74-4b77-9af1-005d9c9f6a99}
diff --git a/src/modules/fancyzones/FancyZones/FancyZonesApp.cpp b/src/modules/fancyzones/FancyZones/FancyZonesApp.cpp
index afa0bf610c..97faec65d5 100644
--- a/src/modules/fancyzones/FancyZones/FancyZonesApp.cpp
+++ b/src/modules/fancyzones/FancyZones/FancyZonesApp.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
#include
@@ -20,6 +21,14 @@ FancyZonesApp::FancyZonesApp(const std::wstring& appName, const std::wstring& ap
InitializeWinhookEventIds();
m_app = MakeFancyZones(reinterpret_cast(&__ImageBase), std::bind(&FancyZonesApp::DisableModule, this));
+ m_mainThreadId = GetCurrentThreadId();
+ m_exitEventWaiter = EventWaiter(CommonSharedConstants::FZE_EXIT_EVENT, [&](int err) {
+ if (err == ERROR_SUCCESS)
+ {
+ DisableModule();
+ }
+ });
+
InitHooks();
s_instance = this;
@@ -111,7 +120,7 @@ void FancyZonesApp::InitHooks()
void FancyZonesApp::DisableModule() noexcept
{
- PostQuitMessage(0);
+ PostThreadMessage(m_mainThreadId, WM_QUIT, 0, 0);
}
void FancyZonesApp::HandleWinHookEvent(WinHookEvent* data) noexcept
diff --git a/src/modules/fancyzones/FancyZones/FancyZonesApp.h b/src/modules/fancyzones/FancyZones/FancyZonesApp.h
index b66ba5b540..44c6a306a9 100644
--- a/src/modules/fancyzones/FancyZones/FancyZonesApp.h
+++ b/src/modules/fancyzones/FancyZones/FancyZonesApp.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include
@@ -15,11 +16,14 @@ public:
private:
static inline FancyZonesApp* s_instance = nullptr;
static inline HHOOK s_llKeyboardHook = nullptr;
-
+
winrt::com_ptr m_app;
HWINEVENTHOOK m_objectLocationWinEventHook = nullptr;
std::vector m_staticWinEventHooks;
+ EventWaiter m_exitEventWaiter;
+ DWORD m_mainThreadId;
+
void DisableModule() noexcept;
void InitHooks();
diff --git a/src/modules/fancyzones/FancyZones/main.cpp b/src/modules/fancyzones/FancyZones/main.cpp
index 3112df7fbb..4001673ea3 100644
--- a/src/modules/fancyzones/FancyZones/main.cpp
+++ b/src/modules/fancyzones/FancyZones/main.cpp
@@ -12,6 +12,8 @@
#include
#include
+#include
+
#include
#include
#include
@@ -25,6 +27,9 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_FancyZones_InstanceMut
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
{
+ Shared::Trace::ETWTrace trace{};
+ trace.UpdateState(true);
+
winrt::init_apartment();
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::fancyZonesLoggerName);
@@ -82,6 +87,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
run_message_loop();
Trace::UnregisterProvider();
-
+
+ trace.Flush();
+
return 0;
}
diff --git a/src/modules/fancyzones/FancyZones/pch.h b/src/modules/fancyzones/FancyZones/pch.h
index 472d051e25..291159e4e8 100644
--- a/src/modules/fancyzones/FancyZones/pch.h
+++ b/src/modules/fancyzones/FancyZones/pch.h
@@ -1,7 +1,6 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include
-#include
#include
#include
#include
diff --git a/src/modules/fancyzones/FancyZonesLib/pch.h b/src/modules/fancyzones/FancyZonesLib/pch.h
index 70a402b0fa..d201dabd0c 100644
--- a/src/modules/fancyzones/FancyZonesLib/pch.h
+++ b/src/modules/fancyzones/FancyZonesLib/pch.h
@@ -8,11 +8,9 @@
#include
#include
#include
-#include
#include
#include
#include
-#include
#include
#include
#include
diff --git a/src/modules/fancyzones/FancyZonesLib/trace.cpp b/src/modules/fancyzones/FancyZonesLib/trace.cpp
index 4c6024fe5a..69e341197a 100644
--- a/src/modules/fancyzones/FancyZonesLib/trace.cpp
+++ b/src/modules/fancyzones/FancyZonesLib/trace.cpp
@@ -10,6 +10,8 @@
#include "FancyZonesLib/FancyZonesDataTypes.h"
#include "FancyZonesLib/util.h"
+#include
+
// Telemetry strings should not be localized.
#define LoggingProviderKey "Microsoft.PowerToys"
@@ -108,19 +110,9 @@ ZoneSetInfo GetZoneSetInfo(_In_opt_ Layout* layout, const LayoutAssignedWindows&
return info;
}
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::FancyZones::EnableFancyZones(bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventEnableFancyZonesKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -130,7 +122,7 @@ void Trace::FancyZones::EnableFancyZones(bool enabled) noexcept
void Trace::FancyZones::OnKeyDown(DWORD vkCode, bool win, bool control, bool inMoveSize) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventKeyDownKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -211,7 +203,7 @@ void Trace::FancyZones::DataChanged() noexcept
activeZoneSetInfo += L", custom zone data was deleted";
}
}
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventZoneSettingsChangedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -226,7 +218,7 @@ void Trace::FancyZones::DataChanged() noexcept
void Trace::FancyZones::EditorLaunched(int value) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventEditorLaunchKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -237,7 +229,7 @@ void Trace::FancyZones::EditorLaunched(int value) noexcept
// Log if an error occurs in FZ
void Trace::FancyZones::Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"FancyZones_Error",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -249,7 +241,7 @@ void Trace::FancyZones::Error(const DWORD errorCode, std::wstring errorMessage,
void Trace::FancyZones::QuickLayoutSwitched(bool shortcutUsed) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventQuickLayoutSwitchKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -260,7 +252,7 @@ void Trace::FancyZones::QuickLayoutSwitched(bool shortcutUsed) noexcept
void Trace::FancyZones::SnapNewWindowIntoZone(Layout* activeLayout, const LayoutAssignedWindows& layoutWindows) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeLayout, layoutWindows);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventSnapNewWindowIntoZone,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -273,7 +265,7 @@ void Trace::FancyZones::SnapNewWindowIntoZone(Layout* activeLayout, const Layout
void Trace::FancyZones::KeyboardSnapWindowToZone(Layout* activeLayout, const LayoutAssignedWindows& layoutWindows) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeLayout, layoutWindows);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventKeyboardSnapWindowToZone,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -299,7 +291,7 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept
auto nextTabHotkeyStr = HotKeyToString(settings.nextTabHotkey);
auto prevTabHotkeyStr = HotKeyToString(settings.prevTabHotkey);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventSettingsKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -337,7 +329,7 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept
void Trace::VirtualDesktopChanged() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventDesktopChangedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -346,7 +338,7 @@ void Trace::VirtualDesktopChanged() noexcept
void Trace::WorkArea::KeyUp(WPARAM wParam) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventWorkAreaKeyUpKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -357,7 +349,7 @@ void Trace::WorkArea::KeyUp(WPARAM wParam) noexcept
void Trace::WorkArea::MoveOrResizeStarted(_In_opt_ Layout* activeLayout, const LayoutAssignedWindows& layoutWindows) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeLayout, layoutWindows);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventMoveOrResizeStartedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -370,7 +362,7 @@ void Trace::WorkArea::MoveOrResizeStarted(_In_opt_ Layout* activeLayout, const L
void Trace::WorkArea::MoveOrResizeEnd(_In_opt_ Layout* activeLayout, const LayoutAssignedWindows& layoutWindows) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeLayout, layoutWindows);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventMoveOrResizeEndedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -383,7 +375,7 @@ void Trace::WorkArea::MoveOrResizeEnd(_In_opt_ Layout* activeLayout, const Layou
void Trace::WorkArea::CycleActiveZoneSet(_In_opt_ Layout* activeLayout, const LayoutAssignedWindows& layoutWindows, InputMode mode) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeLayout, layoutWindows);
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
EventCycleActiveZoneSetKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/fancyzones/FancyZonesLib/trace.h b/src/modules/fancyzones/FancyZonesLib/trace.h
index 3bef5cc8c1..db4206fd1f 100644
--- a/src/modules/fancyzones/FancyZonesLib/trace.h
+++ b/src/modules/fancyzones/FancyZonesLib/trace.h
@@ -1,16 +1,15 @@
#pragma once
+#include
+
struct Settings;
class Layout;
class LayoutAssignedWindows;
-class Trace
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
- class FancyZones
+ class FancyZones : public telemetry::TraceBase
{
public:
static void EnableFancyZones(bool enabled) noexcept;
@@ -26,7 +25,7 @@ public:
static void SettingsTelemetry(const Settings& settings) noexcept;
static void VirtualDesktopChanged() noexcept;
- class WorkArea
+ class WorkArea : public telemetry::TraceBase
{
public:
enum class InputMode
diff --git a/src/modules/fancyzones/FancyZonesModuleInterface/dllmain.cpp b/src/modules/fancyzones/FancyZonesModuleInterface/dllmain.cpp
index 40d0aea08f..f138c43200 100644
--- a/src/modules/fancyzones/FancyZonesModuleInterface/dllmain.cpp
+++ b/src/modules/fancyzones/FancyZonesModuleInterface/dllmain.cpp
@@ -205,8 +205,9 @@ private:
if (m_hProcess)
{
- TerminateProcess(m_hProcess, 0);
SendFZECloseEvent();
+ WaitForSingleObject(m_hProcess, 1500);
+ TerminateProcess(m_hProcess, 0);
m_hProcess = nullptr;
}
}
diff --git a/src/modules/fancyzones/FancyZonesModuleInterface/pch.h b/src/modules/fancyzones/FancyZonesModuleInterface/pch.h
index d70de4e4d4..9dc1f70972 100644
--- a/src/modules/fancyzones/FancyZonesModuleInterface/pch.h
+++ b/src/modules/fancyzones/FancyZonesModuleInterface/pch.h
@@ -5,7 +5,5 @@
#include
#include
#include
-#include
-#include
#include
#include
diff --git a/src/modules/fancyzones/FancyZonesTests/UnitTests/UnitTests.vcxproj b/src/modules/fancyzones/FancyZonesTests/UnitTests/UnitTests.vcxproj
index f1c2e8975e..72f540c0dc 100644
--- a/src/modules/fancyzones/FancyZonesTests/UnitTests/UnitTests.vcxproj
+++ b/src/modules/fancyzones/FancyZonesTests/UnitTests/UnitTests.vcxproj
@@ -1,5 +1,6 @@
-
+
16.0
@@ -83,6 +84,7 @@
+
diff --git a/src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj b/src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj
index 913e885fa5..e3303f759b 100644
--- a/src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj
+++ b/src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj
@@ -131,6 +131,9 @@ MakeAppx.exe pack /d . /p $(OutDir)ImageResizerContextMenuPackage.msix /nv
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{18b3db45-4ffe-4d01-97d6-5223feee1853}
diff --git a/src/modules/imageresizer/ImageResizerContextMenu/dllmain.cpp b/src/modules/imageresizer/ImageResizerContextMenu/dllmain.cpp
index 347475fd90..31335d59a3 100644
--- a/src/modules/imageresizer/ImageResizerContextMenu/dllmain.cpp
+++ b/src/modules/imageresizer/ImageResizerContextMenu/dllmain.cpp
@@ -7,6 +7,7 @@
#include
#include
+#include
#include
#include
#include
@@ -20,6 +21,7 @@
using namespace Microsoft::WRL;
HINSTANCE g_hInst = 0;
+Shared::Trace::ETWTrace trace(L"ImageResizerContextMenu");
#define BUFSIZE 4096 * 4
@@ -134,6 +136,7 @@ public:
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
try
{
+ trace.UpdateState(true);
Trace::Invoked();
HRESULT hr = S_OK;
@@ -145,6 +148,9 @@ public:
Trace::InvokedRet(hr);
+ trace.UpdateState(false);
+ trace.Flush();
+
return hr;
}
CATCH_RETURN();
diff --git a/src/modules/imageresizer/ImageResizerLib/pch.h b/src/modules/imageresizer/ImageResizerLib/pch.h
index dcca9b830b..3664d7390e 100644
--- a/src/modules/imageresizer/ImageResizerLib/pch.h
+++ b/src/modules/imageresizer/ImageResizerLib/pch.h
@@ -13,6 +13,4 @@
#include
#include
-#include
-
#endif //PCH_H
diff --git a/src/modules/imageresizer/ImageResizerLib/trace.cpp b/src/modules/imageresizer/ImageResizerLib/trace.cpp
index 352af3676a..1c0caef2c3 100644
--- a/src/modules/imageresizer/ImageResizerLib/trace.cpp
+++ b/src/modules/imageresizer/ImageResizerLib/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,19 +10,9 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
void Trace::EnableImageResizer(_In_ bool enabled) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ImageResizer_EnableImageResizer",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -28,10 +20,9 @@ void Trace::EnableImageResizer(_In_ bool enabled) noexcept
TraceLoggingBoolean(enabled, "Enabled"));
}
-
void Trace::Invoked() noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ImageResizer_Invoked",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -40,7 +31,7 @@ void Trace::Invoked() noexcept
void Trace::InvokedRet(_In_ HRESULT hr) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ImageResizer_InvokedRet",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -50,7 +41,7 @@ void Trace::InvokedRet(_In_ HRESULT hr) noexcept
void Trace::QueryContextMenuError(_In_ HRESULT hr) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"ImageResizer_QueryContextMenuError",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/imageresizer/ImageResizerLib/trace.h b/src/modules/imageresizer/ImageResizerLib/trace.h
index 9ff1e49f4e..a337e70b03 100644
--- a/src/modules/imageresizer/ImageResizerLib/trace.h
+++ b/src/modules/imageresizer/ImageResizerLib/trace.h
@@ -1,10 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
static void EnableImageResizer(_In_ bool enabled) noexcept;
static void Invoked() noexcept;
static void InvokedRet(_In_ HRESULT hr) noexcept;
diff --git a/src/modules/imageresizer/dll/ContextMenuHandler.cpp b/src/modules/imageresizer/dll/ContextMenuHandler.cpp
index dd86eed5fb..32eced1608 100644
--- a/src/modules/imageresizer/dll/ContextMenuHandler.cpp
+++ b/src/modules/imageresizer/dll/ContextMenuHandler.cpp
@@ -161,8 +161,13 @@ HRESULT CContextMenuHandler::QueryContextMenu(_In_ HMENU hmenu, UINT indexMenu,
if (!InsertMenuItem(hmenu, indexMenu, TRUE, &mii))
{
+ m_etwTrace.UpdateState(true);
+
hr = HRESULT_FROM_WIN32(GetLastError());
Trace::QueryContextMenuError(hr);
+
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
}
else
{
@@ -193,6 +198,8 @@ HRESULT CContextMenuHandler::GetCommandString(UINT_PTR idCmd, UINT uType, _In_ U
HRESULT CContextMenuHandler::InvokeCommand(_In_ CMINVOKECOMMANDINFO* pici)
{
+ m_etwTrace.UpdateState(true);
+
BOOL fUnicode = FALSE;
Trace::Invoked();
HRESULT hr = E_FAIL;
@@ -216,6 +223,10 @@ HRESULT CContextMenuHandler::InvokeCommand(_In_ CMINVOKECOMMANDINFO* pici)
hr = ResizePictures(pici, nullptr);
}
Trace::InvokedRet(hr);
+
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
+
return hr;
}
@@ -427,8 +438,14 @@ HRESULT __stdcall CContextMenuHandler::EnumSubCommands(IEnumExplorerCommand** pp
// psiItemArray contains the list of files that have been selected when the context menu entry is invoked
HRESULT __stdcall CContextMenuHandler::Invoke(IShellItemArray* psiItemArray, IBindCtx* /*pbc*/)
{
+ m_etwTrace.UpdateState(true);
+
Trace::Invoked();
HRESULT hr = ResizePictures(nullptr, psiItemArray);
Trace::InvokedRet(hr);
+
+ m_etwTrace.Flush();
+ m_etwTrace.UpdateState(false);
+
return hr;
}
diff --git a/src/modules/imageresizer/dll/ContextMenuHandler.h b/src/modules/imageresizer/dll/ContextMenuHandler.h
index ba1465df88..abcadfa972 100644
--- a/src/modules/imageresizer/dll/ContextMenuHandler.h
+++ b/src/modules/imageresizer/dll/ContextMenuHandler.h
@@ -5,6 +5,7 @@
#include "pch.h"
#include "Generated Files/resource.h"
#include "ImageResizerExt_i.h"
+#include
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
@@ -53,6 +54,7 @@ private:
HBITMAP m_hbmpIcon = nullptr;
std::wstring context_menu_caption;
std::wstring context_menu_caption_here;
+ Shared::Trace::ETWTrace m_etwTrace{ L"ImageResizerExt" };
};
OBJECT_ENTRY_AUTO(__uuidof(ContextMenuHandler), CContextMenuHandler)
\ No newline at end of file
diff --git a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj
index 90bcd8e357..df038e2c43 100644
--- a/src/modules/imageresizer/dll/ImageResizerExt.vcxproj
+++ b/src/modules/imageresizer/dll/ImageResizerExt.vcxproj
@@ -80,12 +80,14 @@
false
-
+
+
false
-
+
+
Create
@@ -120,6 +122,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/imageresizer/dll/pch.h b/src/modules/imageresizer/dll/pch.h
index 4fef14e85a..a6dd9999a9 100644
--- a/src/modules/imageresizer/dll/pch.h
+++ b/src/modules/imageresizer/dll/pch.h
@@ -22,4 +22,3 @@
#include
#include
-#include
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp
index 260e4c1f5c..5b18b791f0 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp
+++ b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp
@@ -80,7 +80,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
std::wstring keysForShortcutToEdit = L"";
std::wstring action = L"";
-
// do some parsing of the cmdline arg to see if we need to behave different
// like, single edit mode, or "delete" mode.
// These extra args are from "OpenEditor" in the KeyboardManagerViewModel
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj
index 149ec0201a..1cc89c157b 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj
+++ b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj
@@ -132,6 +132,9 @@
{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{98537082-0fdb-40de-abd8-0dc5a4269bab}
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp
index 6bf0994e3f..3597107808 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp
@@ -8,6 +8,8 @@
#include
#include
+#include
+
#include
#include
@@ -426,11 +428,15 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
void CreateEditKeyboardWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration)
{
+ Shared::Trace::ETWTrace trace;
+ trace.UpdateState(true);
+
// Move implementation into the separate method so resources get destroyed correctly
CreateEditKeyboardWindowImpl(hInst, keyboardManagerState, mappingConfiguration);
// Calling ClearXamlIslands() outside of the message loop is not enough to prevent
// Microsoft.UI.XAML.dll from crashing during deinitialization, see https://github.com/microsoft/PowerToys/issues/10906
+ trace.Flush();
Logger::trace("Terminating process {}", GetCurrentProcessId());
Logger::flush();
TerminateProcess(GetCurrentProcess(), 0);
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp
index c85c36cde2..0a2f044765 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditShortcutsWindow.cpp
@@ -6,6 +6,8 @@
#include
#include
+#include
+
#include "KeyboardManagerState.h"
#include "Dialog.h"
#include "KeyDropDownControl.h"
@@ -447,11 +449,15 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
void CreateEditShortcutsWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration, std::wstring keysForShortcutToEdit, std::wstring action)
{
+ Shared::Trace::ETWTrace trace;
+ trace.UpdateState(true);
+
// Move implementation into the separate method so resources get destroyed correctly
CreateEditShortcutsWindowImpl(hInst, keyboardManagerState, mappingConfiguration, keysForShortcutToEdit, action);
// Calling ClearXamlIslands() outside of the message loop is not enough to prevent
// Microsoft.UI.XAML.dll from crashing during deinitialization, see https://github.com/microsoft/PowerToys/issues/10906
+ trace.Flush();
Logger::trace("Terminating process {}", GetCurrentProcessId());
Logger::flush();
TerminateProcess(GetCurrentProcess(), 0);
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/pch.h b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/pch.h
index ffc3ff39aa..316ab36e42 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/pch.h
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/pch.h
@@ -29,8 +29,6 @@
#include
#include
-#include
-
#include
//#include
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.cpp
index 290b11cc41..54ec7539b1 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.cpp
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "trace.h"
+#include
+
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
@@ -8,20 +10,10 @@ TRACELOGGING_DEFINE_PROVIDER(
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
-void Trace::RegisterProvider() noexcept
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider() noexcept
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
// Log number of key remaps when the user uses Edit Keyboard and saves settings
void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount, const DWORD keyToTextCount) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"KeyboardManager_KeyRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -35,7 +27,7 @@ void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCo
// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
void Trace::OSLevelShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"KeyboardManager_OSLevelShortcutRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -48,7 +40,7 @@ void Trace::OSLevelShortcutRemapCount(const DWORD shortcutToShortcutCount, const
// Log number of app specific shortcut remaps when the user uses Edit Shortcuts and saves settings
void Trace::AppSpecificShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"KeyboardManager_AppSpecificShortcutRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
@@ -61,7 +53,7 @@ void Trace::AppSpecificShortcutRemapCount(const DWORD shortcutToShortcutCount, c
// Log if an error occurs in KBM
void Trace::Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept
{
- TraceLoggingWrite(
+ TraceLoggingWriteWrapper(
g_hProvider,
"KeyboardManager_Error",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.h b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.h
index b91f5b625b..9c219bf8e8 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.h
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/trace.h
@@ -1,11 +1,10 @@
#pragma once
-class Trace
+#include
+
+class Trace : public telemetry::TraceBase
{
public:
- static void RegisterProvider() noexcept;
- static void UnregisterProvider() noexcept;
-
// Log number of key remaps when the user uses Edit Keyboard and saves settings
static void KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount, const DWORD keyToTextCount) noexcept;
diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorTest/pch.h b/src/modules/keyboardmanager/KeyboardManagerEditorTest/pch.h
index 6364eacd48..4cf0be54c2 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEditorTest/pch.h
+++ b/src/modules/keyboardmanager/KeyboardManagerEditorTest/pch.h
@@ -1,7 +1,6 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include
-#include
#include
#include
#include
diff --git a/src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj b/src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj
index 55d97e0b00..fd7b4a97c3 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj
+++ b/src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj
@@ -67,6 +67,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {8f021b46-362b-485c-bfba-ccf83e820cbd}
+
{e496b7fc-1e99-4bab-849b-0e8367040b02}
diff --git a/src/modules/keyboardmanager/KeyboardManagerEngine/main.cpp b/src/modules/keyboardmanager/KeyboardManagerEngine/main.cpp
index 31417e9c23..5969ed6cfd 100644
--- a/src/modules/keyboardmanager/KeyboardManagerEngine/main.cpp
+++ b/src/modules/keyboardmanager/KeyboardManagerEngine/main.cpp
@@ -1,4 +1,6 @@
#include "pch.h"
+#include
+#include
#include
#include
#include
@@ -8,6 +10,7 @@
#include
#include
#include