From 223da7bbbcb60a45ecbec592cefa4a20388c87a6 Mon Sep 17 00:00:00 2001 From: Kristen Schau <47155823+krschau@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:47:51 -0400 Subject: [PATCH 1/5] Delete tools/QuietBackgroundProcesses --- .../Common.h | 10 - ...me.QuietBackgroundProcesses.Common.vcxproj | 219 ------ .../DevHome.QuietBackgroundProcesses.idl | 79 -- .../PropertySheet.props | 16 - .../Utility.h | 140 ---- ...Processes.ElevatedServer.Projection.csproj | 37 - ...BackgroundProcesses.ElevatedServer.vcxproj | 216 ------ .../Helpers.cpp | 223 ------ .../Helpers.h | 46 -- .../PerformanceRecorderEngineWinrt.cpp | 364 --------- .../PropertySheet.props | 16 - .../QuietBackgroundProcessesSession.cpp | 141 ---- .../QuietState.cpp | 27 - .../QuietState.h | 16 - .../TimedQuietSession.h | 199 ----- .../Timer.h | 116 --- .../main.cpp | 109 --- .../packages.config | 5 - .../pch.cpp | 4 - .../pch.h | 10 - ...rocesses.PerformanceRecorderEngine.vcxproj | 270 ------- ....PerformanceRecorderEngine.vcxproj.filters | 30 - .../PerformanceRecorderEngine.cpp | 715 ------------------ .../PerformanceRecorderEngine.h | 39 - .../ServiceInformation.h | 96 --- .../dllmain.cpp | 17 - .../packages.config | 4 - .../pch.cpp | 4 - .../pch.h | 10 - ...me.QuietBackgroundProcesses.Server.vcxproj | 253 ------- .../PropertySheet.props | 16 - ...QuietBackgroundProcessesSessionManager.cpp | 110 --- .../main.cpp | 80 -- .../packages.config | 5 - .../pch.cpp | 4 - .../pch.h | 10 - ...DevHome.QuietBackgroundProcesses.UI.csproj | 28 - .../ProcessData.cs | 64 -- .../QuietBackgroundProcessesEvent.cs | 28 - .../Strings/en-us/Resources.resw | 195 ----- .../AnalyticSummaryPopupViewModel.cs | 210 ----- .../QuietBackgroundProcessesViewModel.cs | 342 --------- .../Views/AnalyticSummaryPopup.xaml | 85 --- .../Views/AnalyticSummaryPopup.xaml.cs | 43 -- .../Views/ProcessPerformanceTableControl.xaml | 111 --- .../ProcessPerformanceTableControl.xaml.cs | 31 - .../Views/QuietBackgroundProcessesView.xaml | 58 -- .../QuietBackgroundProcessesView.xaml.cs | 38 - 48 files changed, 4889 deletions(-) delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml delete mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml.cs diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h deleted file mode 100644 index e92ab65a15..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -// Get temporary path for performance data -inline std::filesystem::path GetTemporaryPerformanceDataPath() -{ - auto tempDirectory = std::filesystem::temp_directory_path(); - return std::filesystem::path(tempDirectory) / L"DevHome.QuietMode.PerformanceData.dat"; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj deleted file mode 100644 index bbdd8af811..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj +++ /dev/null @@ -1,219 +0,0 @@ - - - - C++ - - - - - Utlity - true - true - true - true - {4B370E2F-FB1D-4887-90BF-3B72517485CE} - DevHome.QuietBackgroundProcesses.Common - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - StaticLibrary - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - true - - - - - - - - - - - - - - - - NotUsing - - - - - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - - - Windows - false - - - - - - - stdcpp17 - %(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - - - %(Filename).h - $(ProjectDir)$(GeneratedFilesDir)midl - $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - - - <_MdmergeInputs Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'"> - %(Midl.MetadataFileName) - - - - - $(Platform)\$(Configuration)\Merged\ - -n:2 - -v - $(MdmergeParameters) -metadata_dir "$(WindowsSDK_MetadataFoundationPath)" - $(MdmergeParameters) @(MdmergeInputs->'-i "%(Identity)"', ' -') - $(MdmergeParameters) -o "$(MdmergeMergedDir.TrimEnd('\'))" -partial $(MdmergeMergeDepth) - - - $(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd - $(IntDir)$(MSBuildProjectFile).mdmerge.rsp - $(MdMergePath)mdmerge %40"$(MdmergeResponseFile)" - - - - - - - - - copy /Y "$(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd" "$(OutDir)." - - - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl deleted file mode 100644 index 1236b6e6c3..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import "inspectable.idl"; -import "windows.foundation.idl"; - -namespace DevHome.QuietBackgroundProcesses -{ - // Performance Engine types - enum ProcessCategory - { - Unknown, - User, - System, - Developer, - Background, - }; - - [default_interface] - runtimeclass ProcessRow - { - UInt32 Pid { get; }; - String Name { get; }; - String ServiceName { get; }; - String PackageFullName { get; }; - String Aumid { get; }; - String Path { get; }; - ProcessCategory Category { get; }; - Windows.Foundation.DateTime CreateTime { get; }; - Windows.Foundation.DateTime ExitTime { get; }; - - UInt64 SampleCount { get; }; - Double PercentCumulative { get; }; - Double VarianceCumulative { get; }; - Double Sigma4Cumulative { get; }; - Double MaxPercent { get; }; - UInt32 SamplesAboveThreshold { get; }; - - UInt64 TotalCpuTimeInMicroseconds { get; }; - } - - [default_interface] - runtimeclass ProcessPerformanceTable - { - ProcessRow[] Rows { get; }; - } - - [default_interface] - runtimeclass PerformanceRecorderEngine - { - static ProcessPerformanceTable TryGetLastPerformanceRecording(); - - PerformanceRecorderEngine(); - void Start(Windows.Foundation.TimeSpan periodInMs); - ProcessPerformanceTable Stop(); - } - - // Quiet background process types - [default_interface] - runtimeclass QuietBackgroundProcessesSession - { - static QuietBackgroundProcessesSession GetSingleton(); - - Int64 Start(); - ProcessPerformanceTable Stop(); - Boolean IsActive { get; }; - Int64 TimeLeftInSeconds { get; }; - } - - [default_interface] - runtimeclass QuietBackgroundProcessesSessionManager { - QuietBackgroundProcessesSessionManager(); - static Boolean IsFeaturePresent(); - static QuietBackgroundProcessesSession GetSession(); - static QuietBackgroundProcessesSession TryGetSession(); - static Boolean HasLastPerformanceRecording(); - static ProcessPerformanceTable TryGetLastPerformanceRecording(); - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props deleted file mode 100644 index e34141b019..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h deleted file mode 100644 index 9b42fa2fad..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -constexpr bool DEBUG_BUILD = -#if _DEBUG - true; -#else - false; -#endif - -template -struct wrl_module_object_ref -{ - struct details - { - static void wrl_decrement_object_count() - { - auto& module = T::GetModule(); - auto count = module.DecrementObjectCount(); - auto msg = std::wstring(L"WRL: DecrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n"); - OutputDebugStringW(msg.c_str()); - } - }; - - using wrl_module_object_ref_releaser = wil::unique_call; - - wrl_module_object_ref() - { - auto& module = T::GetModule(); - auto count = module.IncrementObjectCount(); - auto msg = std::wstring(L"WRL: IncrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n"); - OutputDebugStringW(msg.c_str()); - - m_moduleReference.activate(); - } - - wrl_module_object_ref(wrl_module_object_ref&& other) noexcept = default; - wrl_module_object_ref& operator=(wrl_module_object_ref&& other) noexcept = default; - - wrl_module_object_ref(const wrl_module_object_ref&) = delete; - wrl_module_object_ref& operator=(const wrl_module_object_ref&) = delete; - - void reset() - { - m_moduleReference.reset(); - } - -private: - - wrl_module_object_ref_releaser m_moduleReference{ false }; -}; - -using wrl_server_process_ref = wrl_module_object_ref>; - -inline std::optional try_get_registry_value_dword(HKEY key, _In_opt_ PCWSTR subKey, _In_opt_ PCWSTR value_name, ::wil::reg::key_access access = ::wil::reg::key_access::read) -{ - wil::unique_hkey hkey; - if (SUCCEEDED(wil::reg::open_unique_key_nothrow(key, subKey, hkey, access))) - { - if (auto keyvalue = wil::reg::try_get_value_dword(hkey.get(), value_name)) - { - return keyvalue.value(); - } - } - return std::nullopt; -} - -inline void WaitForDebuggerIfPresent() -{ - auto waitForDebugger = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"WaitForDebugger"); - - if (waitForDebugger.value_or(0)) - { - while (!IsDebuggerPresent()) - { - Sleep(1000); - }; - DebugBreak(); - } -} - -inline bool IsTokenElevated(HANDLE token) -{ - auto mandatoryLabel = wil::get_token_information(token); - LONG levelRid = static_cast(mandatoryLabel->Label.Sid)->SubAuthority[0]; - return levelRid == SECURITY_MANDATORY_HIGH_RID; -} - -inline void SelfElevate(std::optional const& arguments) -{ - auto path = wil::GetModuleFileNameW(); - - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.lpVerb = L"runas"; - sei.lpFile = path.get(); - sei.lpParameters = arguments.value().c_str(); - sei.hwnd = NULL; - sei.nShow = SW_NORMAL; - - THROW_LAST_ERROR_IF(!ShellExecuteEx(&sei)); -} - -inline std::wstring ParseServerNameArgument(std::wstring_view wargv) -{ - constexpr wchar_t serverNamePrefix[] = L"-ServerName:"; - if (_wcsnicmp(wargv.data(), serverNamePrefix, wcslen(serverNamePrefix)) != 0) - { - THROW_HR(E_UNEXPECTED); - } - return { wargv.data() + wcslen(serverNamePrefix) }; -} - -inline void SetComFastRundownAndNoEhHandle() -{ - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - wil::com_ptr pGlobalOptions; - THROW_IF_FAILED(CoCreateInstance(CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGlobalOptions))); - THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_RO_SETTINGS, COMGLB_FAST_RUNDOWN)); - THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE_ANY)); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj deleted file mode 100644 index b792576ee9..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - enable - enable - x86;x64;arm64 - win-x86;win-x64;win-arm64 - $(CppBaseOutDir)\DevHome.QuietBackgroundProcesses.Common\ - - - - 10.0.19041.0 - DevHome.QuietBackgroundProcesses - $(OutDir) - - - - $(OutDir) - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj deleted file mode 100644 index 959d22e02f..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj +++ /dev/null @@ -1,216 +0,0 @@ - - - - C++ - - - - - - true - true - true - true - {75945141-03ac-4c40-a586-16d463a0ac1b} - DevHome.QuietBackgroundProcesses.ElevatedServer - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - true - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - $(CppOutDir) - - - Application - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - Spectre - - - - - - - - - - - - - - - - - Use - pch.h - $(IntDir)pch.pch - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - Guard - Spectre - - - Windows - false - - - - - - - stdcpp20 - $(SolutionDir)telemetry\DevHome.Telemetry.Native\inc;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine\;%(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - - - _DEBUG;%(PreprocessorDefinitions) - ProgramDatabase - Disabled - - - - - _DEBUG;%(PreprocessorDefinitions) - ProgramDatabase - Disabled - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - {8eb52f7d-d216-49ff-bf16-de06e4695950} - - - {4b370e2f-fb1d-4887-90bf-3b72517485ce} - - - {af5a7fa0-e3e8-44c8-8830-31dd08f583e8} - - - - - - - - - - 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/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp deleted file mode 100644 index 0af73613af..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "DevHomeTelemetryProvider.h" -#include "PerformanceRecorderEngine.h" -#include "Helpers.h" - -void WritePerformanceDataToDisk(_In_ PCWSTR path, const std::span& data) -{ - std::ofstream file(path, std::ios::binary); - if (!file.is_open()) - { - // Handle error - return; - } - - for (const auto& item : data) - { - file.write(reinterpret_cast(&item), sizeof(ProcessPerformanceSummary)); - } - - file.close(); -} - -std::vector ReadPerformanceDataFromDisk(_In_ PCWSTR path) -{ - std::vector data; - - std::ifstream file(path, std::ios::binary); - THROW_WIN32_IF(ERROR_SHARING_VIOLATION, !file.is_open()); - - ProcessPerformanceSummary item; - while (file.read(reinterpret_cast(&item), sizeof(ProcessPerformanceSummary))) - { - data.push_back(item); - } - - file.close(); - return data; -} - -struct ComputerInformation -{ - DWORD processorCount; - std::wstring processor; - std::wstring motherboard; - DWORDLONG ramInMegabytes; -}; - -// Get computer information -ComputerInformation GetComputerInformation() -{ - ComputerInformation computerInfo; - - // Get processor information - SYSTEM_INFO systemInfo = { 0 }; - GetSystemInfo(&systemInfo); - computerInfo.processorCount = systemInfo.dwNumberOfProcessors; - - // Get processor make and model using win32 apis - wil::unique_hkey hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - wchar_t processorName[256] = { 0 }; - DWORD processorNameSize = sizeof(processorName); - if (RegQueryValueEx(hKey.get(), L"ProcessorNameString", nullptr, nullptr, reinterpret_cast(processorName), &processorNameSize) == ERROR_SUCCESS) - { - computerInfo.processor = processorName; - } - } - - // Get motherboard make and model using win32 apis - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - wchar_t biosName[256] = { 0 }; - DWORD biosNameSize = sizeof(biosName); - if (RegQueryValueEx(hKey.get(), L"BaseBoardProduct", nullptr, nullptr, reinterpret_cast(biosName), &biosNameSize) == ERROR_SUCCESS) - { - computerInfo.motherboard = biosName; - } - } - - // Get ram amount using GlobalMemoryStatusEx - MEMORYSTATUSEX memoryStatus = { 0 }; - memoryStatus.dwLength = sizeof(memoryStatus); - if (GlobalMemoryStatusEx(&memoryStatus)) - { - computerInfo.ramInMegabytes = memoryStatus.ullTotalPhys / 1024 / 1024; - } - - return computerInfo; -} - -void UploadPerformanceDataTelemetry(std::chrono::milliseconds samplingPeriod, const std::span& data) -{ - using namespace std::chrono_literals; - - enum class UploadReason - { - None, - MaxPercent, - Sigma4, - StandardDeviation, - SearchIndexer, - }; - - constexpr auto c_quietSessionVersion = 1; - - // Calculate total cpu time usage for all processes - std::chrono::microseconds totalCpuUsageInMicroseconds = std::accumulate(data.begin(), data.end(), 0us, [](std::chrono::microseconds total, const ProcessPerformanceSummary& item) { - return total + std::chrono::microseconds(item.totalCpuTimeInMicroseconds); - }); - - // Begin metrics activity - auto activity = DevHomeTelemetryProvider::QuietBackgroundProcesses_PerformanceMetrics::Start( - c_quietSessionVersion, - samplingPeriod.count(), - totalCpuUsageInMicroseconds.count()); - - // Upload computer information - auto computerInformation = GetComputerInformation(); - activity.QuietBackgroundProcesses_ComputerInfo( - computerInformation.processorCount, - computerInformation.processor.c_str(), - computerInformation.motherboard.c_str(), - computerInformation.ramInMegabytes); - - // Calculate the totalCpuTimeInMicroseconds items aggregated by item.category - std::vector numProcesses(5); - std::vector totalCpuTimesByCategory(5); - for (const auto& item : data) - { - numProcesses[item.category]++; - totalCpuTimesByCategory[item.category] += item.totalCpuTimeInMicroseconds; - } - - // Upload category metrics - activity.QuietBackgroundProcesses_SessionCategoryMetrics( - numProcesses[0], - numProcesses[1], - numProcesses[2], - numProcesses[3], - numProcesses[4], - totalCpuTimesByCategory[0], - totalCpuTimesByCategory[1], - totalCpuTimesByCategory[2], - totalCpuTimesByCategory[3], - totalCpuTimesByCategory[4]); - - // Get system32 path - wchar_t system32Path[MAX_PATH]; - GetSystemDirectory(system32Path, ARRAYSIZE(system32Path)); - - // Choose process information to upload - for (const auto& item : data) - { - // Calculate variance & standard deviation - auto variance = item.varianceCumulative / item.sampleCount; - auto standardDeviation = std::sqrt(variance); - - // Calulate sigma4 variance & sigma4 deviation (it's like variance but to the power of 4 instead of 2). - // Note: This helps identify processes that have a high variance in cpu usage, which otherwise might be difficult - // to notice in a 2 hour time-window. - auto sigma4Variance = item.sigma4Cumulative / item.sampleCount; - auto sigma4Deviation = std::sqrt(std::sqrt(sigma4Variance)); - - UploadReason reason{}; - if (item.maxPercent >= 20.0) - { - reason = UploadReason::MaxPercent; - } - else if (sigma4Deviation >= 4.0) - { - reason = UploadReason::Sigma4; - } - else if (standardDeviation >= 1.0) - { - reason = UploadReason::StandardDeviation; - } - else if (wil::compare_string_ordinal(item.name, L"SearchIndexer.exe", true) == 0) - { - reason = UploadReason::SearchIndexer; - } - else - { - continue; - } - - // Report process name with service name in telemetry - auto processNameTelemetry = std::wstring(item.name); - if (item.serviceName) - { - processNameTelemetry += std::wstring{} + L" (" + item.serviceName + L")"; - } - - activity.QuietBackgroundProcesses_ProcessInfo( - reason, - wil::compare_string_ordinal(item.path, system32Path, true) == 0, - processNameTelemetry.c_str(), - item.category, - item.packageFullName, - - item.sampleCount, - item.maxPercent, - item.samplesAboveThreshold, - sigma4Deviation, - item.totalCpuTimeInMicroseconds); - } - - activity.Stop(); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h deleted file mode 100644 index 1c6f2dbbd7..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -#include -#include - -#include "DevHome.QuietBackgroundProcesses.h" -#include "PerformanceRecorderEngine.h" - -struct com_ptr_deleter -{ - template - void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T p) const - { - if (p) - { - p.reset(); - } - } -}; - -template -using unique_comptr_array = wil::unique_any_array_ptr, ArrayDeleter, com_ptr_deleter>; - -template -unique_comptr_array make_unique_comptr_array(size_t numOfElements) -{ - auto list = unique_comptr_array(reinterpret_cast*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, numOfElements * sizeof(wil::com_ptr_nothrow))), numOfElements); - THROW_IF_NULL_ALLOC(list.get()); - return list; -} - -// Create a performance recorder engine -wil::com_ptr MakePerformanceRecorderEngine(); - -// Read/write the performance data to/from disk -void WritePerformanceDataToDisk(_In_ PCWSTR path, const std::span& data); -std::vector ReadPerformanceDataFromDisk(_In_ PCWSTR path); - -// Upload the performance data to the telemetry service -void UploadPerformanceDataTelemetry(std::chrono::milliseconds samplingPeriod, const std::span& data); diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp deleted file mode 100644 index c7e971cb53..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "Common.h" -#include "TimedQuietSession.h" -#include "DevHome.QuietBackgroundProcesses.h" -#include "PerformanceRecorderEngine.h" -#include "Helpers.h" - - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class ProcessRow : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IProcessRow, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_ProcessRow, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize(ProcessPerformanceSummary summary) noexcept - { - m_summary = summary; - return S_OK; - } - - STDMETHODIMP get_Pid(unsigned int* value) noexcept override - try - { - *value = m_summary.pid; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Name(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.name); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_ServiceName(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.serviceName); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_PackageFullName(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.packageFullName); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Aumid(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.aumid); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Path(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.path); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Category(ABI::DevHome::QuietBackgroundProcesses::ProcessCategory* value) noexcept override - try - { - *value = static_cast(m_summary.category); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_CreateTime(struct ABI::Windows::Foundation::DateTime* value) noexcept override - try - { - INT64 time = m_summary.createTime.dwLowDateTime + ((UINT64)m_summary.createTime.dwHighDateTime << 32); - *value = ABI::Windows::Foundation::DateTime{ time }; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_ExitTime(struct ABI::Windows::Foundation::DateTime* value) noexcept override - try - { - INT64 time = m_summary.exitTime.dwLowDateTime + ((UINT64)m_summary.exitTime.dwHighDateTime << 32); - *value = ABI::Windows::Foundation::DateTime{ time }; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_SampleCount(unsigned __int64* value) noexcept override - try - { - *value = m_summary.sampleCount; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_PercentCumulative(double* value) noexcept override - try - { - *value = m_summary.percentCumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_VarianceCumulative(double* value) noexcept override - try - { - *value = m_summary.varianceCumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Sigma4Cumulative(double* value) noexcept override - try - { - *value = m_summary.sigma4Cumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_MaxPercent(double* value) noexcept override - try - { - *value = m_summary.maxPercent; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_SamplesAboveThreshold(unsigned __int32* value) noexcept override - try - { - *value = m_summary.samplesAboveThreshold; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_TotalCpuTimeInMicroseconds(unsigned __int64* value) noexcept override - try - { - *value = m_summary.totalCpuTimeInMicroseconds; - return S_OK; - } - CATCH_RETURN() - - private: - ProcessPerformanceSummary m_summary; - }; -} - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class ProcessPerformanceTable : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IProcessPerformanceTable, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_ProcessPerformanceTable, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize(unique_process_utilization_monitoring_thread context) noexcept - { - m_context = std::move(context); - return S_OK; - } - - STDMETHODIMP get_Rows(unsigned int* valueLength, ABI::DevHome::QuietBackgroundProcesses::IProcessRow*** value) noexcept override - try - { - std::span span; - wil::unique_cotaskmem_array_ptr summariesCoarray; - std::vector summariesVector; - - if (m_context) - { - // We have a live context, read performance data from it - THROW_IF_FAILED(GetMonitoringProcessUtilization(m_context.get(), nullptr, summariesCoarray.addressof(), summariesCoarray.size_address())); - - // Make span from cotaskmem_array - span = std::span{ summariesCoarray.get(), summariesCoarray.size() }; - } - else - { - // We don't have a live context. Let's try to read performance data from disk. - auto performanceDataFile = GetTemporaryPerformanceDataPath(); - THROW_HR_IF(E_FAIL, !std::filesystem::exists(performanceDataFile)); - - // Make span from vector - summariesVector = ReadPerformanceDataFromDisk(performanceDataFile.c_str()); - span = std::span{ summariesVector }; - } - - // Create IProcessRow entries - auto list = make_unique_comptr_array(span.size()); - for (uint32_t i = 0; i < span.size(); i++) - { - auto& summary = span[i]; - wil::com_ptr row; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&row, summary)); - list[i] = std::move(row); - } - *valueLength = static_cast(span.size()); - *value = (ABI::DevHome::QuietBackgroundProcesses::IProcessRow**)list.release(); - return S_OK; - } - CATCH_RETURN() - - private: - unique_process_utilization_monitoring_thread m_context; - }; -} - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class PerformanceRecorderEngine : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IPerformanceRecorderEngine, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - - // IPerformanceRecorderEngine - STDMETHODIMP Start(ABI::Windows::Foundation::TimeSpan samplingPeriod) noexcept override - try - { - // Convert TimeSpan from 100ns to milliseconds - auto periodInMs = static_cast(samplingPeriod.Duration / 10000); - THROW_IF_FAILED(StartMonitoringProcessUtilization(periodInMs, &m_context)); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP Stop(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - THROW_IF_FAILED(StopMonitoringProcessUtilization(m_context.get())); - - { - // Get the performance data from the monitoring engine - std::chrono::milliseconds samplingPeriod; - wil::unique_cotaskmem_array_ptr summaries; - THROW_IF_FAILED(GetMonitoringProcessUtilization(m_context.get(), &samplingPeriod, summaries.addressof(), summaries.size_address())); - std::span data(summaries.get(), summaries.size()); - - // Write the performance .csv data to disk (if Dev Home is closed, enables user to see the Analytic Summary later) - try - { - auto performanceDataFile = GetTemporaryPerformanceDataPath(); - WritePerformanceDataToDisk(performanceDataFile.c_str(), data); - } - CATCH_LOG(); - - // Upload the performance data telemetry - try - { - UploadPerformanceDataTelemetry(samplingPeriod, data); - } - CATCH_LOG(); - } - - if (result) - { - wil::com_ptr performanceTable; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&performanceTable, std::move(m_context))); - *result = performanceTable.detach(); - } - - // Destroy the performance engine instance - m_context.reset(); - - return S_OK; - } - CATCH_RETURN() - - private: - unique_process_utilization_monitoring_thread m_context; - }; - - class PerformanceRecorderEngineStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine, BaseTrust); - - public: - STDMETHODIMP ActivateInstance(_COM_Outptr_ IInspectable**) noexcept - { - // Disallow activation - must use GetSingleton() - return E_NOTIMPL; - } - - // IPerformanceRecorderEngineStatics - STDMETHODIMP TryGetLastPerformanceRecording(_COM_Outptr_ ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - // Reconstruct a perform table from disk (passing nullptr for context) - wil::com_ptr performanceTable; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&performanceTable, nullptr)); - *result = performanceTable.detach(); - - return S_OK; - } - CATCH_RETURN() - }; - - ActivatableClassWithFactory(PerformanceRecorderEngine, PerformanceRecorderEngineStatics); -} - -wil::com_ptr MakePerformanceRecorderEngine() -{ - using namespace ABI::DevHome::QuietBackgroundProcesses; - wil::com_ptr result; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&result)); - return result; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props deleted file mode 100644 index e34141b019..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp deleted file mode 100644 index 6179b95779..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "TimedQuietSession.h" - -#include "DevHome.QuietBackgroundProcesses.h" - -constexpr auto DEFAULT_QUIET_DURATION = std::chrono::hours(2); - -std::mutex g_mutex; -std::unique_ptr g_activeTimer; - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class QuietBackgroundProcessesSession : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IQuietBackgroundProcessesSession, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - - // IQuietBackgroundProcessesSession - STDMETHODIMP Start(__int64* result) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - - // Stop and discard the previous timer - if (g_activeTimer) - { - g_activeTimer->Cancel(nullptr); - } - - std::chrono::seconds duration = DEFAULT_QUIET_DURATION; - if (auto durationOverride = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"Duration")) - { - duration = std::chrono::seconds(durationOverride.value()); - } - - // Let's make the quiet window a placebo 5 percent of the time - bool placebo = (rand() % 100) < 5; - - // Start timer - g_activeTimer.reset(new TimedQuietSession(placebo, duration)); - - // Return duration for showing countdown - *result = g_activeTimer->TimeLeftInSeconds().count(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP Stop(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - auto lock = std::scoped_lock(g_mutex); - *result = nullptr; - - // Turn off quiet mode and cancel timer - if (g_activeTimer) - { - g_activeTimer->Cancel(result); - g_activeTimer.reset(); - } - - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_IsActive(::boolean* value) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - *value = false; - if (g_activeTimer) - { - *value = g_activeTimer->IsActive(); - } - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_TimeLeftInSeconds(__int64* value) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - *value = 0; - if (g_activeTimer) - { - *value = g_activeTimer->TimeLeftInSeconds().count(); - } - return S_OK; - } - CATCH_RETURN() - }; - - class QuietBackgroundProcessesSessionStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust); - - public: - STDMETHODIMP ActivateInstance(_COM_Outptr_ IInspectable**) noexcept - { - // Disallow activation - must use GetSingleton() - return E_NOTIMPL; - } - - // IQuietBackgroundProcessesSessionStatics - STDMETHODIMP GetSingleton(_COM_Outptr_ IQuietBackgroundProcessesSession** session) noexcept override try - { - // Instanced objects are the only feasible way to manage a COM singleton without keeping a strong - // handle to the server - which keeps it alive. (IWeakReference keeps a strong handle to the server!) - // An 'instance' can be thought of as a 'handle' to 'the singleton' backend. - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(session)); - return S_OK; - } - CATCH_RETURN() - }; - - ActivatableClassWithFactory(QuietBackgroundProcessesSession, QuietBackgroundProcessesSessionStatics); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp deleted file mode 100644 index b6a6fbf14d..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -#include - -#include -#include "QuietState.h" - -namespace QuietState -{ - std::mutex g_mutex; - - void TurnOff() noexcept - { - auto lock = std::scoped_lock(g_mutex); - LOG_IF_FAILED(DisableQuietBackgroundProcesses()); - } - - unique_quietwindowclose_call TurnOn() - { - auto lock = std::scoped_lock(g_mutex); - THROW_IF_FAILED(EnableQuietBackgroundProcesses()); - return unique_quietwindowclose_call{}; - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h deleted file mode 100644 index 92ac8855c7..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#pragma once - -#include - -namespace QuietState -{ - void TurnOff() noexcept; - - using unique_quietwindowclose_call = wil::unique_call; - - unique_quietwindowclose_call TurnOn(); -} - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h deleted file mode 100644 index 6ad27b697c..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "DevHomeTelemetryProvider.h" - -#include "DevHome.QuietBackgroundProcesses.h" - -#include "Timer.h" -#include "QuietState.h" -#include "Helpers.h" - -using ElevatedServerReference = wrl_server_process_ref; - -struct UnelevatedServerReference -{ - wil::com_ptr m_reference; - - UnelevatedServerReference() : - m_reference(wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager)) - { - } - - void reset() - { - m_reference.reset(); - } -}; - - -// TimedQuietSession is a 2 hour "Quiet background processes" timed window that disables quiet -// mode when the timer expires or when explicitly cancelled. It keeps also keeps the server alive. -// -// TimedQuietSession maintains, -// 1. quiet mode signal -// 2. session timer -// 3. handle to session (elevated) server -// 4. handle to manager (unelevated) server -// -// COM server lifetime & process interaction: -// -// Processes: -// DevHome (client) -> UnelevatedServer (manager) -> ElevatedServer (session) -// -// Manager (unelevated server): -// Role of manager is simply allow client to check if session (elevated server) is alive -// without risking launching a UAC prompt. It caches a com proxy interface to session. -// -// Session (elevated server): -// Role of session is to enable/disable quiet mode and keep a timer. -// -// Lifetime: -// - The manager and session keep each other alive. -// -// - The session (TimedQuietSession) runs in ElevatedServer and keeps this elevated server -// alive until timer expiration. -// -// - The session (TimedQuietSession) also keeps the manager (in unelevated server) alive until timer expiration; -// this is only because the manager caches a *strong* handle to the session (elevated server), -// and there is no way to invalidate the session (proxy handle) in the client if we tore down -// this session. (Using IWeakReference does hold a weak reference to the object, but also holds a strong -// reference against the hosting process's lifetime.) -// -// Teardown Sequence: -// When all session timers (elevated) expire, the manager (unelevated) reference is released -> COM triggers -// teardown in unelevated server (assuming DevHome is closed), releasing the cached *strong* reference -// to the session (elevated) -> COM triggers teardown in elevated server. -// -#pragma warning(push) -#pragma warning(disable : 4324) // Avoid WRL alignment warning -struct TimedQuietSession -{ - TimedQuietSession(bool isPlacebo, std::chrono::seconds seconds) - { - // Save activity for telemetry - auto activity = DevHomeTelemetryProvider::QuietBackgroundProcesses_ElevatedServer_Session::Start(isPlacebo, seconds.count()); - - m_intendedDurationInSeconds = seconds; - - m_timer = std::make_unique(seconds, [this]() { - auto lock = std::scoped_lock(m_mutex); - Deactivate(false); - }); - - // Turn on quiet mode - if (isPlacebo) - { - // Don't actaully turn on quiet mode - i.e. control group for quiet mode in telemetry - } - else - { - m_quietState = QuietState::TurnOn(); - } - - // Start performance recorder - ABI::Windows::Foundation::TimeSpan samplingPeriod; - samplingPeriod.Duration = 1000 * 10000; // 1 second - m_performanceRecorderEngine = MakePerformanceRecorderEngine(); - THROW_IF_FAILED(m_performanceRecorderEngine->Start(samplingPeriod)); - - m_activity = activity.TransferToMember(); - } - - TimedQuietSession(TimedQuietSession&& other) noexcept = default; - TimedQuietSession& operator=(TimedQuietSession&& other) noexcept = default; - - TimedQuietSession(const TimedQuietSession&) = delete; - TimedQuietSession& operator=(const TimedQuietSession&) = delete; - - std::chrono::seconds TimeLeftInSeconds() - { - auto lock = std::scoped_lock(m_mutex); - return m_timer->TimeLeftInSeconds(); - } - - bool IsActive() - { - auto lock = std::scoped_lock(m_mutex); - return (bool)m_quietState; - } - - void Cancel(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) - { - auto lock = std::scoped_lock(m_mutex); - - Deactivate(true, result); - m_timer->Cancel(); - - // Destruct timer on another thread because it's destructor is blocking - auto destructionThread = std::thread([timer = std::move(m_timer)]() { - // destruct timer here - }); - - destructionThread.detach(); - } - -private: - void Deactivate(bool manuallyStopped, ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result = nullptr) - { - if (m_deactivated) - { - return; - } - - // Continue activity on current thread - auto activity = m_activity.TransferToCurrentThread(); - - auto totalQuietWindowTime = m_intendedDurationInSeconds - m_timer->TimeLeftInSeconds(); - - // Turn off quiet mode - m_quietState.reset(); - - // Stop the performance recorder - if (m_performanceRecorderEngine) - { - LOG_IF_FAILED(m_performanceRecorderEngine->Stop(result)); - } - - // Disable performance recorder - m_performanceRecorderEngine.reset(); - - // Release lifetime handles to this elevated server and unelevated client server - m_unelevatedServer.reset(); - m_elevatedServer.reset(); - - // Only allow deactivation once - m_deactivated = true; - - // Stop activity - activity.Stop(manuallyStopped, totalQuietWindowTime.count()); - } - - UnelevatedServerReference m_unelevatedServer; // Manager server - ElevatedServerReference m_elevatedServer; // Session server (this server) - - bool m_deactivated{}; - QuietState::unique_quietwindowclose_call m_quietState{ false }; - std::unique_ptr m_timer; - wil::com_ptr m_performanceRecorderEngine; - std::mutex m_mutex; - - DevHomeTelemetryProvider::QuietBackgroundProcesses_ElevatedServer_Session m_activity; - std::chrono::seconds m_intendedDurationInSeconds{}; -}; -#pragma warning(pop) diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h deleted file mode 100644 index e112b6513f..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Utility.h" - -#if _DEBUG || NDEBUG -#define TRACK_SECONDS_LEFT -#endif - -using namespace std::chrono_literals; - -class Timer -{ -public: - Timer(std::chrono::seconds seconds, std::function callback) : - m_callback(std::forward>(callback)), - m_startTime(std::chrono::steady_clock::now()), - m_duration(seconds), - m_timerThread(std::thread(&Timer::TimerThread, this)) - { - } - - Timer(Timer&& other) noexcept = default; - Timer& operator=(Timer&& other) noexcept = default; - - Timer(const Timer&) = delete; - Timer& operator=(const Timer&) = delete; - - ~Timer() - { - if (m_timerThread.joinable()) - { - m_timerThread.join(); - } - } - - void Cancel() - { - OutputDebugStringW(L"Timer: Cancelling\n"); - - auto lock = std::scoped_lock(m_mutex); - - // Disable the callback from being called... - m_cancelled = true; - - // ... wake up the timer thread. - m_cancelCondition.notify_one(); - } - - std::chrono::seconds TimeLeftInSeconds() - { - auto lock = std::scoped_lock(m_mutex); - if (m_cancelled) - { - return 0s; - } - - auto secondsLeft = CalculateSecondsLeft(); - return std::max(secondsLeft, 0s); - } - -private: - std::chrono::seconds CalculateSecondsLeft() - { - auto now = std::chrono::steady_clock::now(); - auto elapsed = std::chrono::duration_cast(now - m_startTime); - auto secondsLeft = m_duration - elapsed; -#ifdef TRACK_SECONDS_LEFT - m_secondsLeft = secondsLeft; -#endif - return secondsLeft; - } - - void TimerThread() - { - // Pause until timer expired or cancelled - { - auto lock = std::unique_lock(m_mutex); - - m_cancelCondition.wait_for(lock, m_duration, [this] { - return this->m_cancelled; - }); - } - - // Do the callback - if (!this->m_cancelled) - { - this->m_callback(); - } - - OutputDebugStringW(L"Timer: Finished\n"); - } - - std::chrono::steady_clock::time_point m_startTime{}; - std::chrono::seconds m_duration{}; - std::thread m_timerThread; - std::mutex m_mutex; - bool m_cancelled{}; - std::condition_variable m_cancelCondition; - std::function m_callback; - -#ifdef TRACK_SECONDS_LEFT - std::chrono::seconds m_secondsLeft = std::chrono::seconds::max(); -#endif -}; diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp deleted file mode 100644 index 067085996e..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "Utility.h" -#include "TimedQuietSession.h" -#include "QuietState.h" - -int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try -{ - constexpr auto ELEVATED_SERVER_STARTED_EVENT_NAME = L"Global\\DevHome_QuietBackgroundProcesses_ElevatedServer_Started"; - - if (wargc < 1) - { - THROW_HR(E_INVALIDARG); - } - - // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.ElevatedServer" - auto serverName = ParseServerNameArgument(wargv); - - if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.ElevatedServer", true) != 0) - { - THROW_HR(E_INVALIDARG); - } - - // Let's self-elevate and terminate - if (!IsTokenElevated(GetCurrentProcessToken())) - { - wil::unique_event elevatedServerRunningEvent; - elevatedServerRunningEvent.create(wil::EventOptions::ManualReset, ELEVATED_SERVER_STARTED_EVENT_NAME); - - // Launch elevated instance - SelfElevate(wargv); - - // Wait for the *actual* elevated server instance to register its winrt classes with COM before shutting down - elevatedServerRunningEvent.wait(); - return 0; - } - - WaitForDebuggerIfPresent(); - - auto unique_rouninitialize_call = wil::RoInitialize(); - - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - SetComFastRundownAndNoEhHandle(); - - // To be safe, force quiet mode off to begin the proceedings in case we leaked the machine state previously - QuietState::TurnOff(); - - std::mutex mutex; - bool comFinished{}; - std::condition_variable finishCondition; - -#pragma warning(push) -#pragma warning(disable : 4324) // Avoid WRL alignment warning - - // Register WRL callback when all objects are destroyed - auto& module = Microsoft::WRL::Module::Create([&] { - // The last instance object of the module is released - { - auto lock = std::unique_lock(mutex); - comFinished = true; - } - finishCondition.notify_one(); - }); - -#pragma warning(pop) - - // Register WinRT activatable classes - module.RegisterObjects(); - auto unique_wrl_registration_cookie = wil::scope_exit([&module]() { - module.UnregisterObjects(); - }); - - // Tell the unelevated server instance that we've registered our winrt classes with COM (so it can terminate) - wil::unique_event elevatedServerRunningEvent; - elevatedServerRunningEvent.open(ELEVATED_SERVER_STARTED_EVENT_NAME); - elevatedServerRunningEvent.SetEvent(); - - // Wait for all server references to release (implicitly also waiting for timers to finish via CoAddRefServerProcess) - auto lock = std::unique_lock(mutex); - - finishCondition.wait(lock, [&] { - return comFinished; - }); - - // Safety - QuietState::TurnOff(); - - return 0; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config deleted file mode 100644 index 1e9a0103c3..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp deleted file mode 100644 index d58e93e60c..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h deleted file mode 100644 index 601ace8be4..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#pragma once - -#define NOMINMAX - -#include -#include -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj deleted file mode 100644 index c60233ad25..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj +++ /dev/null @@ -1,270 +0,0 @@ - - - - C++ - - - - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - {af5a7fa0-e3e8-44c8-8830-31dd08f583e8} - DynamicLibrary - DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine - en-US - 14.0 - false - Windows Store - 10.0.22621.0 - 10.0.17134.0 - 10.0 - $(CppOutDir) - - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - true - Spectre - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - - Use - false - stdcpp20 - - - Console - false - false - onecore.lib;onecoreuap_apiset.lib;%(AdditionalDependencies) - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - NDEBUG;%(PreprocessorDefinitions) - Guard - Guard - Guard - - - true - true - - - - - - - - - - - Create - Create - Create - Create - Create - Create - Create - Create - 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/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters deleted file mode 100644 index 2a68852d4e..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms - - - {a4747e26-49cd-412b-b5ad-2d499887d0d5} - - - - - - - - - - - inc - - - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp deleted file mode 100644 index 33d8d949f2..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "PerformanceRecorderEngine.h" -#include "ServiceInformation.h" - -// 2 percent is the threshold for a process to be considered as a high CPU consumer -#define CPU_TIME_ABOVE_THRESHOLD_STRIKE_VALUE 2.0f - -enum class ProcessCategory -{ - Unknown, - User, - System, - Developer, - Background, -}; - -struct ProcessPerformanceInfo -{ - // Process id - wil::unique_process_handle process; - ULONG pid{}; - - // Process info - std::wstring name; - std::optional serviceName; - std::wstring path; - std::optional packageFullName; - std::optional aumid; - ProcessCategory category{}; - FILETIME createTime{}; - FILETIME exitTime{}; - - // CPU times - FILETIME startUserTime{}; - FILETIME startKernelTime{}; - FILETIME previousUserTime{}; - FILETIME currentUserTime{}; - FILETIME previousKernelTime{}; - FILETIME currentKernelTime{}; - - // Sampling - uint64_t sampleCount{}; - double percentCumulative{}; - double varianceCumulative{}; - double sigma4Cumulative{}; - double maxPercent{}; - uint32_t samplesAboveThreshold{}; -}; - -// Process Categories -std::set c_user = { - L"chrome.exe", - L"OUTLOOK.exe", - L"EXCEL.exe", - L"explorer.exe", - L"WINWORD.exe", - L"POWERPOINT.exe", - L"OfficeClickToRun.exe", - L"Microsoft.SharePoint.exe", - L"msedge.exe", - L"msedgewebview2.exe", - L"ShellExperienceHost.exe", - L"StartMenuExperienceHost.exe", - L"smartscreen.exe", - L"sihost.exe", - L"SystemSettings.exe", - L"electron.exe", - L"CrmSandbox.exe", - L"ms-teams.exe", - L"TextInputHost.exe", - L"UserOOBEBroker.exe", - L"WebViewHost.exe", - L"Widgets.exe", - L"WidgetService.exe", - L"XboxGameBarWidgets.exe", - L"teams.exe" -}; -std::set c_system = { - L"System", - L"Registry", - L"Secure System", - L"audiodg.exe", - L"ctfmon.exe", - L"LogonUI.exe", - L"MpDefenderCoreService.exe", - L"MpDlpService.exe", - L"ShellHost.exe", - L"smss.exe", - L"spoolsv.exe", - L"wininit.exe", - L"lsass.exe" -}; -std::set c_developer = { - L"cmd.exe", - L"conhost.exe", - L"console.exe", - L"OpenConsole.exe", - L"powershell.exe", - L"cl.exe", - L"link.exe", - L"devenv.exe", - L"DevHome.exe", - L"DevHomeGitHubExtension.exe", - L"python.exe", - L"build.exe", - L"msbuild.exe", - L"windbg.exe", - L"windbgx.exe", - L"EngHost.exe", - L"DbgX.Shell.exe", - L"GVFS.Mount.exe", - L"GVFS.Service.exe", - L"GVFS.ServiceUI.exe", - L"vscode.exe", - L"code.exe", - L"cpptools.exe", - L"notepad.exe", - L"notepad++.exe", - L"Wex.Services.exe", - L"Taskmgr.exe", - L"wpa.exe", - L"wpr.exe", - L"CalculatorApp.exe", - L"npm.exe", - L"winget.exe", - L"chocolatey.exe", - L"pip.exe", - L"vshost.exe", - L"VSSVC.exe", - L"VBCSCompiler.exe", - L"vcpkgsrv.exe", - L"WindowsTerminal.exe", - L"WindowsPackageManagerServer.exe", - L"reSearch.exe" -}; -std::set c_vms = { - L"vmmem", - L"vmwp.exe", // actual process name for 'vmmem' - L"vmcompute.exe", - L"vmconnect.exe", - L"vmwp.exe", - L"vmms.exe" -}; -std::set c_background = { - L"services.exe", - L"svchost.exe", - L"SCNotification.exe", - L"SecurityHealthyService.exe", - L"DevHome.QuietBackgroundProcesses.Server.exe", - L"DevHome.QuietBackgroundProcesses.ElevatedServer.exe", - L"OneDrive.exe", - L"MsMpEng.exe", - L"MsSense.exe", - L"NdrSetup.exe", - L"NisSrv.exe", - L"RuntimeBroker.exe", - L"rundll32.exe", - L"SearchHost.exe", - L"SenseCE.exe", - L"SenseNdr.exe", - L"SenseNdrX.exe", - L"SenseTVM.exe", - L"SearchIndexer.exe", - L"taskhostw.exe", - L"winlogon.exe", -}; - -ProcessCategory GetCategory(DWORD pid, std::wstring_view processName) -{ - auto search = [&](std::wstring_view processName, const auto& list) - { - auto it = std::find_if(list.begin(), list.end(), [&](const auto& elem) - { - return wil::compare_string_ordinal(processName, elem, true) == 0; - }); - auto found = (it != list.end()); - return found; - }; - - if (pid == 4) - { - // PID 4 is the System process - return ProcessCategory::System; - } - if (search(processName.data(), c_user)) - { - return ProcessCategory::User; - } - if (search(processName.data(), c_system)) - { - return ProcessCategory::System; - } - if (search(processName.data(), c_developer)) - { - return ProcessCategory::Developer; - } - if (search(processName.data(), c_vms)) - { - return ProcessCategory::Developer; - } - if (search(processName.data(), c_background)) - { - return ProcessCategory::Background; - } - return ProcessCategory::Unknown; -} - -template -void copystr(wchar_t(&dst)[N], const std::optional& src) -{ - wcscpy_s(dst, N, src.value_or(L"").substr(0, N - 1).c_str()); -} - -template -wil::unique_cotaskmem_array_ptr make_unique_cotaskmem_array_ptr(size_t numOfElements) -{ - wil::unique_cotaskmem_array_ptr result; - T* ptr = reinterpret_cast(CoTaskMemAlloc(sizeof(T) * numOfElements)); - THROW_IF_NULL_ALLOC(ptr); - *result.addressof() = ptr; - *result.size_address() = numOfElements; - return result; -} - -std::chrono::file_clock::time_point FileTimeToTimePoint(const FILETIME& fileTime) -{ - ULARGE_INTEGER uli; - uli.LowPart = fileTime.dwLowDateTime; - uli.HighPart = fileTime.dwHighDateTime; - std::chrono::file_clock::duration d{ (static_cast(fileTime.dwHighDateTime) << 32) | fileTime.dwLowDateTime }; - std::chrono::file_clock::time_point tp{ d }; - return tp; -} - -std::string FiletimeToString(const FILETIME& ft) -{ - std::chrono::file_clock::duration d{ (static_cast(ft.dwHighDateTime) << 32) | ft.dwLowDateTime }; - std::chrono::file_clock::time_point tp{ d }; - return std::format("{:%Y-%m-%d %H:%M}\n", tp); -} - -std::chrono::microseconds CpuTimeDuration(FILETIME previous, FILETIME current) -{ - if (CompareFileTime(&previous, ¤t) >= 0) - { - return std::chrono::microseconds(0); - } - - auto filetimeDeltaIn100ns = FileTimeToTimePoint(current) - FileTimeToTimePoint(previous); - auto durationMicroseconds = std::chrono::duration_cast(filetimeDeltaIn100ns); - return durationMicroseconds; -} - -int GetVirtualNumCpus() -{ - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwNumberOfProcessors; -} - -template -std::span GetPids(DWORD (&pidArray)[size]) -{ - DWORD needed; - THROW_IF_WIN32_BOOL_FALSE(EnumProcesses(pidArray, sizeof(pidArray), &needed)); - return { &pidArray[0], needed / sizeof(DWORD) }; -} - -std::optional TryGetPackageFullNameFromTokenHelper(HANDLE token) -{ - wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1]{}; - uint32_t packageFullNameLength = ARRAYSIZE(packageFullName); - if (GetPackageFullNameFromToken(token, &packageFullNameLength, packageFullName)) - { - return std::nullopt; - } - return std::wstring { packageFullName }; -} - -std::optional TryGetAppUserModelIdFromTokenHelper(HANDLE token) -{ - wchar_t aumid[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{}; - uint32_t aumidLength = ARRAYSIZE(aumid); - if (GetApplicationUserModelIdFromToken(token, &aumidLength, aumid) != ERROR_SUCCESS) - { - return std::nullopt; - } - return std::wstring { aumid }; -} - -std::optional TryGetProcessName(HANDLE processHandle) -{ - static wchar_t s_buffer[MAX_PATH * 2]; - if (GetModuleFileNameExW(processHandle, nullptr, s_buffer, _countof(s_buffer)) > 0) - { - return s_buffer; - } - return std::nullopt; -} - -ProcessPerformanceInfo MakeProcessPerformanceInfo(DWORD processId) -{ - auto process = wil::unique_process_handle{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId) }; - if (!process) - { - // We can't open csrss.exe, so we'll just skip processes we can't open - auto info = ProcessPerformanceInfo{}; - info.process = nullptr; - info.pid = processId; - LOG_LAST_ERROR_MSG("Failed to open process handle for PID: %d", processId); - } - - auto processPathString = TryGetProcessName(process.get()); - - auto path = std::filesystem::path(processPathString.value_or(L"")); - - FILETIME createTime{}; - FILETIME exitTime{}; - FILETIME kernelTime{}; - FILETIME userTime{}; - if (process) - { - THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(process.get(), &createTime, &exitTime, &kernelTime, &userTime)); - } - - std::optional packageFullName; - std::optional aumid; - wil::unique_handle processToken; - if (process) - { - if (OpenProcessToken(process.get(), TOKEN_QUERY, &processToken)) - { - packageFullName = TryGetPackageFullNameFromTokenHelper(processToken.get()); - aumid = TryGetAppUserModelIdFromTokenHelper(processToken.get()); - } - else - { - PCWSTR processPath = processPathString ? processPathString.value().c_str() : L""; - LOG_LAST_ERROR_MSG("Failed to open process token for PID: %d (%ls)", processId, processPath); - } - } - - auto info = ProcessPerformanceInfo{}; - info.process = std::move(process); - info.pid = processId; - info.name = path.filename().wstring(); - info.path = path.parent_path().wstring(); - info.packageFullName = packageFullName; - info.aumid = aumid; - info.category = GetCategory(info.pid, info.name); - info.createTime = createTime; - - // Start times - info.startUserTime = userTime; - info.startKernelTime = kernelTime; - - info.previousUserTime = userTime; - info.currentUserTime = userTime; - info.previousKernelTime = kernelTime; - info.currentKernelTime = kernelTime; - - return info; -} - -bool UpdateProcessPerformanceInfo(ProcessPerformanceInfo& info) -{ - FILETIME createTime, exitTime, kernelTime, userTime; - THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(info.process.get(), &createTime, &exitTime, &kernelTime, &userTime)); - - if (exitTime.dwHighDateTime != 0 || exitTime.dwLowDateTime != 0) - { - info.exitTime = exitTime; - return false; - } - - info.previousUserTime = info.currentUserTime; - info.currentUserTime = userTime; - info.previousKernelTime = info.currentKernelTime; - info.currentKernelTime = kernelTime; - return true; -} - -struct cancellation_mechanism -{ - std::atomic m_cancelled{}; - std::mutex m_mutex; - std::condition_variable m_cancelCondition; - - void cancel() - { - auto lock = std::scoped_lock(m_mutex); - m_cancelled = true; - m_cancelCondition.notify_all(); - } - - bool wait_for_cancel(std::chrono::milliseconds duration) - { - auto lock = std::unique_lock(m_mutex); - auto cancelHappened = m_cancelCondition.wait_for(lock, duration, [this] { - return m_cancelled.load(); - }); - return cancelHappened; - } -}; - -struct MonitorThread -{ - cancellation_mechanism m_cancellationMechanism; - std::thread m_thread; - std::mutex m_dataMutex; - - // Tracking all our process infos - std::map m_runningProcesses; - std::vector m_terminatedProcesses; - - // Info - std::chrono::milliseconds m_samplingPeriod; - - MonitorThread(std::chrono::milliseconds periodMs) - { - m_samplingPeriod = periodMs; - - if (periodMs.count() <= 0) - { - THROW_HR(E_INVALIDARG); - } - - m_thread = std::thread([this, periodMs]() { - try - { - auto numCpus = GetVirtualNumCpus(); - - auto serviceInformation = ServiceInformation::RunningServiceInformation(); - - while (true) - { - if (m_cancellationMechanism.m_cancelled) - { - break; - } - - // Check for new processes to track - DWORD pidArray[2048]; - auto pids = GetPids(pidArray); - - auto lock = std::scoped_lock(m_dataMutex); - for (auto& pid : pids) - { - // Ignore process "0" - the 'SYSTEM 'System' process - if (pid == 0) - { - continue; - } - - // Make a new entry - if (!m_runningProcesses.contains(pid)) - { - try - { - // Create new process info object - auto processInfo = MakeProcessPerformanceInfo(pid); - - // Add the service name if it's an svchost.exe process - processInfo.serviceName = serviceInformation.TryGetServiceName(processInfo.pid, processInfo.name); - - // Add process to running processes map - m_runningProcesses[pid] = std::move(processInfo); - } - CATCH_LOG(); - } - } - - // Update counts for each tracked process - for (auto it = m_runningProcesses.begin(); it != m_runningProcesses.end(); ) - { - auto pid = it->first; - - // Get entry - auto& info = it->second; - - if (!info.process) - { - // The process couldn't be opened, so we'll skip this entry - ++it; - continue; - } - - // Update entry - try - { - if (!UpdateProcessPerformanceInfo(info)) - { - // The process terminated - - // Destroy the process handle - info.process.reset(); - - // Move from the map to the terminated list - m_terminatedProcesses.push_back(std::move(info)); - it = m_runningProcesses.erase(it); - - // Remove from running services names - serviceInformation.ForgetService(pid); - continue; - } - } - catch (...) - { - ++it; - continue; - } - - // Collect cpuTime for process - auto cpuTime = CpuTimeDuration(info.previousUserTime, info.currentUserTime); - cpuTime += CpuTimeDuration(info.previousKernelTime, info.currentKernelTime); - - double percent = (double)cpuTime.count() / std::chrono::duration_cast(periodMs).count() / (double)numCpus * 100.0f; - double variance = (double)std::pow(percent, 2.0f); - double sigma4 = (double)std::pow(percent, 4.0f); - - info.sampleCount++; - info.percentCumulative += percent; - info.varianceCumulative += variance; - info.sigma4Cumulative += sigma4; - if (percent > info.maxPercent) - { - info.maxPercent = percent; - } - if (percent > CPU_TIME_ABOVE_THRESHOLD_STRIKE_VALUE) - { - info.samplesAboveThreshold++; - } - - ++it; - } - - // Wait for interval period or user cancellation - if (m_cancellationMechanism.wait_for_cancel(periodMs)) - { - // User cancelled - break; - } - } - } - CATCH_LOG(); - }); - } - - void Cancel() - { - m_cancellationMechanism.cancel(); - if (m_thread.joinable()) - { - m_thread.join(); - } - } - - std::chrono::milliseconds GetSamplingPeriod() - { - return m_samplingPeriod; - } - - std::vector GetProcessPerformanceSummaries() - { - auto lock = std::scoped_lock(m_dataMutex); - - std::vector summaries; - auto MakeSummary = [](const ProcessPerformanceInfo& info) - { - auto summary = ProcessPerformanceSummary{}; - auto totalUserTime = CpuTimeDuration(info.startUserTime, info.currentUserTime); - auto totalKernelTime = CpuTimeDuration(info.startKernelTime, info.currentKernelTime); - - // Process info - summary.pid = info.pid; - if (summary.pid == 4) - { - copystr(summary.name, L"[System]"); - } - else if (info.name.empty()) - { - copystr(summary.name, L"[unk]"); - } - else - { - copystr(summary.name, info.name); - } - copystr(summary.serviceName, info.serviceName); - copystr(summary.packageFullName, info.packageFullName); - copystr(summary.aumid, info.aumid); - copystr(summary.path, info.path); - summary.category = static_cast(info.category); - summary.createTime = info.createTime; - summary.exitTime = info.exitTime; - - // Sampling - summary.sampleCount = info.sampleCount; - summary.percentCumulative = info.percentCumulative; - summary.varianceCumulative = info.varianceCumulative; - summary.sigma4Cumulative = info.sigma4Cumulative; - summary.maxPercent = info.maxPercent; - summary.samplesAboveThreshold = info.samplesAboveThreshold; - - // Other - summary.totalCpuTimeInMicroseconds = totalUserTime.count() + totalKernelTime.count(); - - if (summary.sampleCount <= 0) - { - summary.sampleCount = 0; - } - return summary; - }; - - // Add summaries for running processes - for (auto const& [key, info] : m_runningProcesses) - { - summaries.push_back(MakeSummary(info)); - } - - // Add summaries for terminated processes - for (auto const& info : m_terminatedProcesses) - { - summaries.push_back(MakeSummary(info)); - } - return summaries; - } -}; - -// -// Exports -// - -extern "C" __declspec(dllexport) HRESULT StartMonitoringProcessUtilization(uint32_t periodInMs, void** context) noexcept -try -{ - auto periodMs = std::chrono::milliseconds(periodInMs); - auto monitorThread = std::make_unique(periodMs); - *context = static_cast(monitorThread.release()); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT StopMonitoringProcessUtilization(void* context) noexcept -try -{ - auto monitorThread = reinterpret_cast(context); - monitorThread->Cancel(); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT DeleteMonitoringProcessUtilization(void* context) noexcept -try -{ - if (!context) - { - return S_OK; - } - auto monitorThread = std::unique_ptr(reinterpret_cast(context)); - monitorThread->Cancel(); - monitorThread.reset(); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT GetMonitoringProcessUtilization(void* context, std::chrono::milliseconds* samplingPeriodInMs, ProcessPerformanceSummary** ppSummaries, size_t* summaryCount) noexcept -try -{ - auto monitorThread = reinterpret_cast(context); - auto summaries = monitorThread->GetProcessPerformanceSummaries(); - - if (samplingPeriodInMs) - { - *samplingPeriodInMs = monitorThread->GetSamplingPeriod(); - } - - // Alloc summaries block - auto ptrSummaries = make_unique_cotaskmem_array_ptr(summaries.size()); - auto i = 0; - for (auto const& summary : summaries) - { - auto& dst = ptrSummaries.get()[i++]; - dst = summary; - } - - *summaryCount = ptrSummaries.size(); - *ppSummaries = ptrSummaries.release(); - - return S_OK; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h deleted file mode 100644 index 671c97344f..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -struct ProcessPerformanceSummary -{ - // Process info - ULONG pid{}; - wchar_t name[64]{}; - wchar_t serviceName[64]{}; - wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1]{}; - wchar_t aumid[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{}; - wchar_t path[MAX_PATH * 2]{}; - uint32_t category{}; - FILETIME createTime{}; - FILETIME exitTime{}; - - // Sampling - uint64_t sampleCount{}; - double percentCumulative{}; - double varianceCumulative{}; - double sigma4Cumulative{}; - double maxPercent{}; - uint32_t samplesAboveThreshold{}; - - // Other - uint64_t totalCpuTimeInMicroseconds{}; -}; - -extern "C" __declspec(dllexport) HRESULT StartMonitoringProcessUtilization(uint32_t periodInMs, void** context) noexcept; -extern "C" __declspec(dllexport) HRESULT StopMonitoringProcessUtilization(void* context) noexcept; -extern "C" __declspec(dllexport) HRESULT GetMonitoringProcessUtilization(void* context, std::chrono::milliseconds* samplingPeriodInMs, ProcessPerformanceSummary** ppSummaries, size_t* summaryCount) noexcept; -extern "C" __declspec(dllexport) HRESULT DeleteMonitoringProcessUtilization(void* context) noexcept; - -using unique_process_utilization_monitoring_thread = wil::unique_any; diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h deleted file mode 100644 index 4d7c379e5b..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -#include -#include -#include - -namespace ServiceInformation -{ - inline bool IsSvchost(std::wstring_view name) - { - return wil::compare_string_ordinal(name, L"svchost.exe", true) == 0; - } - - inline std::map GetRunningServiceNames() - { - SC_HANDLE m_hScmManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); - THROW_LAST_ERROR_IF(m_hScmManager == NULL); - - std::unique_ptr services{}; - ULONG servicesCount = 0; - ULONG servicesSize = 0; - - while (true) - { - // Get services - ULONG resumeIndex = 0; - if (EnumServicesStatusEx(m_hScmManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)services.get(), servicesSize, &servicesSize, &servicesCount, &resumeIndex, NULL)) - { - break; - } - - THROW_LAST_ERROR_IF(GetLastError() != ERROR_MORE_DATA); - - // Increase the buffer size and try again. - servicesSize *= 2; - services.reset(reinterpret_cast(new BYTE[servicesSize])); - THROW_IF_NULL_ALLOC(services); - ZeroMemory(services.get(), servicesSize); - } - - auto map = std::map(); - for (ULONG index = 0; index < servicesCount; index++) - { - map.emplace(services.get()[index].ServiceStatusProcess.dwProcessId, services.get()[index].lpServiceName); - } - return map; - } - - class RunningServiceInformation - { - public: - std::optional TryGetServiceName(DWORD pid, std::wstring_view name) noexcept try - { - // Check if we have the service name cached - auto it = m_runningServiceNames.find(pid); - if (it != m_runningServiceNames.end()) - { - return it->second; - } - - // If the process is svchost.. - if (IsSvchost(name)) - { - // Update cache.. - m_runningServiceNames = GetRunningServiceNames(); - - // ..and try again - auto it = m_runningServiceNames.find(pid); - if (it != m_runningServiceNames.end()) - { - return it->second; - } - } - - return std::nullopt; - } - catch (...) - { - return std::nullopt; - } - - void ForgetService(DWORD pid) - { - m_runningServiceNames.erase(pid); - } - - private: - std::map m_runningServiceNames; - }; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp deleted file mode 100644 index b503a9ba44..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config deleted file mode 100644 index 09be25d9e4..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp deleted file mode 100644 index 40e691ba78..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h deleted file mode 100644 index f4b4e69378..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj deleted file mode 100644 index fdd8d25faf..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj +++ /dev/null @@ -1,253 +0,0 @@ - - - - C++ - - - - - - true - true - true - true - {80805B43-CE75-4C6E-92F8-F385C1039E53} - DevHome.QuietBackgroundProcesses.Server - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - Application - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - true - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - - - - - - - - - - - - - - - Use - pch.h - $(IntDir)pch.pch - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - - - Windows - false - - - - - - - stdcpp17 - C++ - $(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;%(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - %(Filename).h - $(ProjectDir)$(GeneratedFilesDir)midl - $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - NDEBUG;%(PreprocessorDefinitions) - Guard - Guard - Guard - Guard - - - true - true - - - - - - - - - Create - - - - - - - - - - - - {4b370e2f-fb1d-4887-90bf-3b72517485ce} - - - - - - - - - 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/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props deleted file mode 100644 index e34141b019..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp deleted file mode 100644 index 3d74ecd239..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include "DevHome.QuietBackgroundProcesses.h" - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class QuietBackgroundProcessesSessionManager : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IQuietBackgroundProcessesSessionManager, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - }; - - class QuietBackgroundProcessesSessionManagerStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust); - - public: - // IActivationFactory method - STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) noexcept - try - { - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(ppvObject)); - return S_OK; - } - CATCH_RETURN() - - // IQuietBackgroundProcessesSessionManagerStatics - STDMETHODIMP IsFeaturePresent(_Out_ boolean* isPresent) noexcept override try - { - THROW_IF_FAILED(IsQuietBackgroundProcessesFeaturePresent((bool*)isPresent)); - return S_OK; - } - CATCH_RETURN(); - - STDMETHODIMP GetSession(_Outptr_result_nullonfailure_ IQuietBackgroundProcessesSession** session) noexcept override - try - { - auto lock = std::scoped_lock(m_mutex); - *session = nullptr; - - if (!m_sessionReference) - { - auto factory = wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession); - THROW_IF_FAILED(factory->GetSingleton(&m_sessionReference)); - } - m_sessionReference.copy_to(session); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP TryGetSession(_COM_Outptr_result_maybenull_ IQuietBackgroundProcessesSession** session) noexcept override try - { - auto lock = std::scoped_lock(m_mutex); - m_sessionReference.try_copy_to(session); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP TryGetLastPerformanceRecording(_COM_Outptr_ ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - auto factory = wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine); - THROW_IF_FAILED(factory->TryGetLastPerformanceRecording(result)); - - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP HasLastPerformanceRecording(boolean* result) noexcept override - try - { - *result = std::filesystem::exists(GetTemporaryPerformanceDataPath()); - return S_OK; - } - CATCH_RETURN() - - private: - std::mutex m_mutex; - wil::com_ptr m_sessionReference; - }; - - ActivatableClassWithFactory(QuietBackgroundProcessesSessionManager, QuietBackgroundProcessesSessionManagerStatics); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp deleted file mode 100644 index 54ae2b766b..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "Utility.h" - -int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try -{ - WaitForDebuggerIfPresent(); - - if (wargc < 1) - { - THROW_HR(E_INVALIDARG); - } - - // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.Server" - auto serverName = ParseServerNameArgument(wargv); - - if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.Server", true) != 0) - { - THROW_HR(E_INVALIDARG); - } - - auto unique_rouninitialize_call = wil::RoInitialize(); - - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - SetComFastRundownAndNoEhHandle(); - - std::mutex mutex; - bool comFinished{}; - std::condition_variable finishCondition; - -#pragma warning(push) -#pragma warning(disable: 4324) // Avoid WRL alignment warning - - // Register WRL callback when all objects are destroyed - auto& module = Microsoft::WRL::Module::Create([&] { - // The last instance object of the module is released - { - auto lock = std::unique_lock(mutex); - comFinished = true; - } - finishCondition.notify_one(); - }); - -#pragma warning(pop) - - // Register WinRT activatable classes - module.RegisterObjects(); - auto unique_wrl_registration_cookie = wil::scope_exit([&module]() { - module.UnregisterObjects(); - }); - - // Wait for all server references to release - auto lock = std::unique_lock(mutex); - - finishCondition.wait(lock, [&] { - return comFinished; - }); - - return 0; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config deleted file mode 100644 index 47df16ce82..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp deleted file mode 100644 index 40e691ba78..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h deleted file mode 100644 index 9d6cb89293..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#define NOMINMAX - -#include -#include -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj deleted file mode 100644 index 74f170c199..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - - DevHome.QuietBackgroundProcesses.UI - x86;x64;arm64 - win-x86;win-x64;win-arm64 - true - enable - - - - - - - - - - MSBuild:Compile - - - - - - $(DefaultXamlRuntime) - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs deleted file mode 100644 index 01e898712e..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace DevHome.QuietBackgroundProcesses.UI; - -public class ProcessData -{ - public enum ProcessCategory - { - Unknown, - User, - System, - Developer, - Background, - } - - public ProcessData() - { - Name = string.Empty; - ServiceName = string.Empty; - DisplayName = string.Empty; - PackageFullName = string.Empty; - Aumid = string.Empty; - Path = string.Empty; - } - - public long Pid { get; set; } - - public string Name { get; set; } - - public string ServiceName { get; set; } - - public string DisplayName { get; set; } - - public string PackageFullName { get; set; } - - public string Aumid { get; set; } - - public string Path { get; set; } - - public ProcessCategory Category { get; set; } - - public DateTimeOffset CreateTime { get; set; } - - public DateTimeOffset ExitTime { get; set; } - - public ulong Samples { get; set; } - - public double Percent { get; set; } - - public double StandardDeviation { get; set; } - - public double Sigma4Deviation { get; set; } - - public double MaxPercent { get; set; } - - public TimeSpan TimeAboveThreshold { get; set; } - - public double TimeAboveThresholdInMinutes { get; set; } - - public ulong TotalCpuTimeInMicroseconds { get; set; } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs deleted file mode 100644 index 6a2507b760..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; -using Windows.Foundation.Diagnostics; - -namespace DevHome.QuietBackgroundProcesses.UI; - -[EventData] -public class QuietBackgroundProcessesEvent : EventBase -{ - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public LoggingOpcode Opcode { get; } - - public QuietBackgroundProcessesEvent(LoggingOpcode opcode = LoggingOpcode.Info) - { - Opcode = opcode; - } - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw deleted file mode 100644 index 2532574fb8..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Quiet background processes - The name of the Quiet background processes page - - - Start session - Button that starts a quiet background session - - - End session - Button that stops a quiet background session - - - Last session length: - Length of the previously run quiet session - - - Enhance resource management while developing for a maximum of 2 hours - Description of the Quiet background processes feature - - - Quiet background processes - Inline title of the Quiet background processes feature - - - An analytic summary will be available after a session has completed. The summary will include an overview of process resource consumption. The analytic summary is not available while feature is active. - A description of the Quiet background processes time window - - - Link to docs - Link that launches documentation - - - Provide feedback - Link that launches feedback - - - Related links - Label for the doc links - - - Analytic summary - Button to open the analytic summary dialog - - - - - Analysis of process CPU utilization while the session was in use. Calculated amount of time that the process used CPU above the designated threshold. - Desciption of the analytic summary page - - - Sort by - Label for the combo box for sorting - - - Sort-by combo box - Accessible name for the "Sort by" dropdown combo box in the analytic summary - - - Process - Sortby dropdown option - - - Type - Sortby dropdown option - - - CPU above threshold - Sortby dropdown option - - - Search for a process - Label for analytic summary save report button - - - Analytic Summary - Title of the analytic summary page - - - Save report - Label for analytic summary save report button - - - Close - Label for analytic summary close button - - - - - Process - Table heading for Process column - - - Type - Table heading for Type column - - - CPU above threshold - Table heading for 'CPU time above threshold' column - - - The time that a process spent using the CPU at greater than 2% utilization. - Sortby dropdown option - - - min - Abbreviation for the word minutes - - - - - Feature not supported on this version of Windows - Indicates that this OS isn't new enough to support the feature - - - There was an error that prevented the session from starting - Something went wrong when running the session - - - There was an error when retrieving the active quiet session - Something went wrong when asking the server if a quiet session is ongoing - - - There was an error when getting the time remaning in the session - Something went wrong when asking the server for time remaining - - - Unable to cancel session - Something went wrong when cancelling the session - - - There was an error retrieving the analytic summary - Something went wrong getting the analytic summary - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs deleted file mode 100644 index b183ada4c7..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.WinUI.Collections; -using DevHome.Telemetry; -using Serilog; - -namespace DevHome.QuietBackgroundProcesses.UI.ViewModels; - -public partial class AnalyticSummaryPopupViewModel : ObservableObject -{ - // Enum for process category - public enum ProcessTableColumn - { - Process, - Type, - CPUAboveThreshold, - } - - private readonly ILogger _log = Log.ForContext("SourceContext", nameof(AnalyticSummaryPopupViewModel)); - private readonly List _processDatas = new(); - - public int SortComboBoxIndex { get; set; } - - public AdvancedCollectionView ProcessDatasAd { get; private set; } - - private ProcessData.ProcessCategory ConvertProcessType(DevHome.QuietBackgroundProcesses.ProcessCategory inputType) - { - return (ProcessData.ProcessCategory)inputType; - } - - public AnalyticSummaryPopupViewModel(QuietBackgroundProcesses.ProcessPerformanceTable? performanceTable) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_AnalyticSummary_Open", LogLevel.Info, new QuietBackgroundProcessesEvent()); - - try - { - if (performanceTable != null) - { - var rows = performanceTable.Rows; - foreach (var row in rows) - { - if (row != null) - { - var sampleCount = row.SampleCount; - var sampleDuration = 1; - - var displayName = row.Name; - if (!string.IsNullOrEmpty(row.ServiceName)) - { - displayName += " (" + row.ServiceName + ")"; - } - - var entry = new ProcessData - { - Pid = row.Pid, - Name = row.Name, - ServiceName = row.ServiceName, - DisplayName = displayName, - PackageFullName = row.PackageFullName, - Aumid = row.Aumid, - Path = row.Path, - Category = ConvertProcessType(row.Category), - CreateTime = row.CreateTime, - ExitTime = row.ExitTime, - Samples = row.SampleCount, - Percent = row.PercentCumulative / sampleCount, - StandardDeviation = (float)Math.Sqrt(row.VarianceCumulative / sampleCount), - Sigma4Deviation = (float)Math.Sqrt(Math.Sqrt(row.Sigma4Cumulative / sampleCount)), - MaxPercent = row.MaxPercent, - TimeAboveThreshold = TimeSpan.FromSeconds(row.SamplesAboveThreshold * sampleDuration), - TotalCpuTimeInMicroseconds = row.TotalCpuTimeInMicroseconds, - }; - - entry.TimeAboveThresholdInMinutes = entry.TimeAboveThreshold.TotalMinutes; - _processDatas.Add(entry); - } - } - } - } - catch (Exception ex) - { - _log.Error("Error populating performance summary table", ex); - } - - ProcessDatasAd = new AdvancedCollectionView(_processDatas, true); - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Pid", SortDirection.Descending)); - } - - private ProcessTableColumn GetProcessTableColumnFromString(string value) - { - if (string.Equals(value, "Process", StringComparison.Ordinal)) - { - return ProcessTableColumn.Process; - } - else if (string.Equals(value, "Type", StringComparison.Ordinal)) - { - return ProcessTableColumn.Type; - } - else if (string.Equals(value, "CPUAboveThreshold", StringComparison.Ordinal)) - { - return ProcessTableColumn.CPUAboveThreshold; - } - - throw new ArgumentException("Invalid value for ProcessTableColumn"); - } - - [RelayCommand] - public void FilterProcessesTextInputChanged(string filterExpression) - { - ProcessDatasAd.Filter = item => - { - try - { - if (item is DevHome.QuietBackgroundProcesses.UI.ProcessData process) - { - return - process.Name.Contains(filterExpression, StringComparison.OrdinalIgnoreCase) - || process.Category.ToString().Contains(filterExpression, StringComparison.OrdinalIgnoreCase) - || process.TimeAboveThreshold.Minutes.ToString(CultureInfo.InvariantCulture).Contains(filterExpression, StringComparison.OrdinalIgnoreCase); - } - - return false; - } - catch (Exception ex) - { - _log.Error("Filtering failed", ex); - } - - return true; - }; - - ProcessDatasAd.RefreshFilter(); - } - - [RelayCommand] - public void SortProcessesComboBoxChanged(string selectedValueString) - { - ProcessDatasAd.SortDescriptions.Clear(); - - var selectedValue = GetProcessTableColumnFromString(selectedValueString); - switch (selectedValue) - { - case ProcessTableColumn.Process: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Name", SortDirection.Ascending)); - break; - case ProcessTableColumn.Type: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Category", SortDirection.Descending)); - break; - case ProcessTableColumn.CPUAboveThreshold: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("TimeAboveThreshold", SortDirection.Descending)); - break; - } - } - - public void SaveReport(string filePath) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_AnalyticSummary_Save", LogLevel.Info, new QuietBackgroundProcessesEvent()); - - // Save the report to a .csv - using (StreamWriter writer = new StreamWriter(filePath)) - { - // Write the .csv header - writer.WriteLine("Pid," + - "Name," + - "Samples," + - "Percent," + - "StandardDeviation," + - "Sigma4Deviation," + - "MaxPercent," + - "TimeAboveThreshold," + - "TotalCpuTimeInMicroseconds," + - "ServiceName," + - "PackageFullName," + - "Aumid," + - "Path," + - "Category," + - "CreateTime," + - "ExitTime"); - - // Write each item from the list to the file - foreach (var data in this._processDatas) - { - var row = $"{data.Pid}," + - $"{data.Name}," + - $"{data.Samples}," + - $"{data.Percent}," + - $"{data.StandardDeviation}," + - $"{data.Sigma4Deviation}," + - $"{data.MaxPercent}," + - $"{data.TimeAboveThreshold}," + - $"{data.TotalCpuTimeInMicroseconds}," + - $"{data.ServiceName}," + - $"{data.PackageFullName}," + - $"{data.Aumid}," + - $"{data.Path}," + - $"{data.Category}," + - $"{data.CreateTime}," + - $"{data.ExitTime}"; - writer.WriteLine(row); - } - } - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs deleted file mode 100644 index d570ee5cd2..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Globalization; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.WinUI; -using DevHome.Common.Services; -using DevHome.Telemetry; -using Microsoft.UI.Dispatching; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Media; -using Serilog; -using Windows.Foundation.Diagnostics; - -namespace DevHome.QuietBackgroundProcesses.UI.ViewModels; - -public partial class QuietBackgroundProcessesViewModel : ObservableObject -{ - private readonly ILogger _log = Log.ForContext("SourceContext", nameof(QuietBackgroundProcessesViewModel)); - - private readonly IExperimentationService _experimentationService; - - private readonly TimeSpan _zero = new(0, 0, 0); - private readonly TimeSpan _oneSecond = new(0, 0, 1); - private readonly DispatcherQueue _dispatcherQueue; - private TimeSpan _sessionDuration; - private QuietBackgroundProcessesSession? _session; - private ProcessPerformanceTable? _table; - - [ObservableProperty] - private bool _isFeaturePresent; - - [ObservableProperty] - private bool _isAnalyticSummaryAvailable; - - [ObservableProperty] - private string _countdownTimer; - - [ObservableProperty] - private string _sessionStateText; - - [ObservableProperty] - private SolidColorBrush _sessionStateTextColor; - - [ObservableProperty] - private bool _quietButtonEnabled; - - [ObservableProperty] - private bool _quietButtonChecked; - - [ObservableProperty] - private string? _quietButtonText; - - private QuietBackgroundProcessesSession GetSession() - { - if (_session == null) - { - _session = QuietBackgroundProcessesSessionManager.GetSession(); - } - - return _session; - } - - private string GetString(string id) - { - var stringResource = new StringResource("DevHome.QuietBackgroundProcesses.UI.pri", "DevHome.QuietBackgroundProcesses.UI/Resources"); - return stringResource.GetLocalized(id); - } - - private string GetStatusString(string id) - { - return GetString("QuietBackgroundProcesses_Status_" + id); - } - - private void SetErrorString(string id) - { - QuietButtonEnabled = false; - SessionStateText = GetStatusString(id); - SessionStateTextColor = (SolidColorBrush)Application.Current.Resources["SystemFillColorCriticalBrush"]; - } - - public bool IsQuietBackgroundProcessesFeatureEnabled => _experimentationService.IsFeatureEnabled("QuietBackgroundProcessesExperiment"); - - public QuietBackgroundProcessesViewModel( - IExperimentationService experimentationService, - DispatcherQueue dispatcherQueue) - { - _experimentationService = experimentationService; - _dispatcherQueue = dispatcherQueue; - _countdownTimer = string.Empty; - _sessionStateText = GetString("QuietBackgroundProcesses_Description"); - - // Set the default text color since there's no way to acquire it from - // the theme in code (and we want to change it when an error happens). - _sessionStateTextColor = (SolidColorBrush)Application.Current.Resources["TextFillColorSecondaryBrush"]; - _dispatcherTimer = new DispatcherTimer(); - } - - public async Task LoadViewModelContentAsync() - { - await Task.Run(async () => - { - if (!IsQuietBackgroundProcessesFeatureEnabled) - { - return; - } - - var isFeaturePresent = false; - try - { - isFeaturePresent = QuietBackgroundProcessesSessionManager.IsFeaturePresent(); - } - catch (Exception ex) - { - _log.Error(ex, "COM error"); - } - - var isAvailable = false; - isAvailable = _table != null; - if (!isAvailable) - { - try - { - isAvailable = QuietBackgroundProcessesSessionManager.HasLastPerformanceRecording(); - } - catch (Exception ex) - { - _log.Error(ex, "COM error"); - } - } - - var running = false; - long? timeLeftInSeconds = null; - if (isFeaturePresent) - { - // Check if an existing quiet session is running. - // Note: GetIsActive() won't ever launch a UAC prompt, but GetTimeRemaining() will if no session is running - so be careful with call order - running = GetIsActive(); - if (running) - { - timeLeftInSeconds = GetTimeRemaining(); - } - } - - // Update the UI thread - await _dispatcherQueue.EnqueueAsync(() => - { - IsFeaturePresent = isFeaturePresent; - IsAnalyticSummaryAvailable = isAvailable; - if (IsFeaturePresent) - { - QuietButtonEnabled = true; - - // Resume countdown if there's an existing quiet window - SetQuietSessionRunningState(running, timeLeftInSeconds); - } - else - { - SetErrorString("FeatureNotSupported"); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Start"); - } - }); - }); - } - - private void SetQuietSessionRunningState(bool running, long? timeLeftInSeconds = null) - { - if (running) - { - var seconds = timeLeftInSeconds ?? GetTimeRemaining(); - StartCountdownTimer(seconds); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Stop"); - IsAnalyticSummaryAvailable = false; - } - else - { - _dispatcherTimer?.Stop(); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Start"); - if (!IsAnalyticSummaryAvailable) - { - IsAnalyticSummaryAvailable = QuietBackgroundProcessesSessionManager.HasLastPerformanceRecording(); - } - } - - QuietButtonChecked = !running; - } - - [RelayCommand] - public void QuietButtonClicked() - { - if (QuietButtonChecked) - { - try - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_Session", LogLevel.Critical, new QuietBackgroundProcessesEvent(LoggingOpcode.Start)); - - // Launch the server, which then elevates itself, showing a UAC prompt - var timeLeftInSeconds = GetSession().Start(); - _sessionDuration = TimeSpan.FromSeconds(timeLeftInSeconds); - SetQuietSessionRunningState(true, timeLeftInSeconds); - } - catch (Exception ex) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_SessionStartError", LogLevel.Critical, new QuietBackgroundProcessesEvent()); - - SetErrorString("SessionStartError"); - _log.Error(ex, "QuietBackgroundProcessesSession::Start failed"); - } - } - else - { - try - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_Session", LogLevel.Critical, new QuietBackgroundProcessesEvent(LoggingOpcode.Stop)); - - _table = GetSession().Stop(); - IsAnalyticSummaryAvailable = _table != null; - SetQuietSessionRunningState(false); - CountdownTimer = GetLastSessionLengthString(_sessionDuration - _secondsLeft); - } - catch (Exception ex) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_SessionStopError", LogLevel.Critical, new QuietBackgroundProcessesEvent()); - - SetErrorString("UnableToCancelSession"); - _log.Error(ex, "QuietBackgroundProcessesSession::Stop failed"); - } - } - } - - private bool GetIsActive() - { - try - { - _session = QuietBackgroundProcessesSessionManager.TryGetSession(); - if (_session != null) - { - return _session.IsActive; - } - } - catch (Exception ex) - { - SetErrorString("UnableToFindActiveSession"); - _log.Error(ex, "QuietBackgroundProcessesSession::IsActive failed"); - } - - return false; - } - - private int GetTimeRemaining() - { - try - { - return (int)GetSession().TimeLeftInSeconds; - } - catch (Exception ex) - { - SetErrorString("UnableToGetTimeLeft"); - _log.Error(ex, "QuietBackgroundProcessesSession::TimeLeftInSeconds failed"); - return 0; - } - } - - private DispatcherTimer _dispatcherTimer; - private TimeSpan _secondsLeft; - - private void StartCountdownTimer(long timeLeftInSeconds) - { - if (timeLeftInSeconds <= 0) - { - return; - } - - _dispatcherTimer = new DispatcherTimer(); - _dispatcherTimer.Tick += DispatcherTimer_Tick; - _dispatcherTimer.Interval = new TimeSpan(0, 0, 1); - _secondsLeft = new TimeSpan(0, 0, (int)timeLeftInSeconds); - _dispatcherTimer.Start(); - - CountdownTimer = _secondsLeft.ToString(); - } - - private void DispatcherTimer_Tick(object? sender, object e) - { - // Subtract 1 second - _secondsLeft = _secondsLeft.Subtract(_oneSecond); - - // Every 2 minutes ask the server for the actual time remaining (to resolve any drift) - if (_secondsLeft.Seconds % 120 == 0) - { - _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining()); - } - - var sessionEnded = false; - if (_secondsLeft.CompareTo(_zero) <= 0) - { - // The window should be closed, but let's confirm with the server - if (!GetSession().IsActive) - { - sessionEnded = true; - } - } - - if (sessionEnded) - { - SetQuietSessionRunningState(false); - var lastSessionLength = _sessionDuration - _secondsLeft; - _secondsLeft = _zero; - CountdownTimer = GetLastSessionLengthString(lastSessionLength); - } - else - { - CountdownTimer = _secondsLeft.ToString(); // CultureInfo.InvariantCulture - } - } - - private string GetLastSessionLengthString(TimeSpan lastSessionLength) - { - return GetString("QuietBackgroundProcesses_Time_LastSessionLength") + " " + lastSessionLength.ToString("g", CultureInfo.CurrentCulture); - } - - public ProcessPerformanceTable? GetProcessPerformanceTable() - { - if (_table == null) - { - try - { - _table = QuietBackgroundProcessesSessionManager.TryGetLastPerformanceRecording(); - } - catch (Exception ex) - { - SetErrorString("UnableToGetAnalyticSummary"); - _log.Error(ex, "QuietBackgroundProcessesSessionManager.TryGetLastPerformanceRecording failed"); - } - } - - return _table; - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml deleted file mode 100644 index 292b01c34d..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - 652 - 700 - 650 - 36 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs deleted file mode 100644 index e42652f8b3..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.Common.Windows.FileDialog; -using DevHome.QuietBackgroundProcesses.UI.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.QuietBackgroundProcesses.UI.Views; - -public sealed partial class AnalyticSummaryPopup : ContentDialog -{ - private readonly Window _mainWindow; - - public AnalyticSummaryPopupViewModel ViewModel - { - get; - } - - public AnalyticSummaryPopup(QuietBackgroundProcesses.ProcessPerformanceTable? performanceTable) - { - _mainWindow = Application.Current.GetService(); - - ViewModel = new AnalyticSummaryPopupViewModel(performanceTable); - - this.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style; - this.DefaultButton = ContentDialogButton.Primary; - this.InitializeComponent(); - } - - private void SaveReportButtonClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) - { - using var fileDialog = new WindowSaveFileDialog(); - fileDialog.AddFileType("CSV files", ".csv"); - - var filePath = fileDialog.Show(_mainWindow); - if (filePath != null) - { - ViewModel.SaveReport(filePath); - } - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml deleted file mode 100644 index 8ad3f2dcd5..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs deleted file mode 100644 index 364220422c..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using DevHome.QuietBackgroundProcesses.UI.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.QuietBackgroundProcesses.UI.Views; - -public sealed partial class ProcessPerformanceTableControl : UserControl -{ - public ObservableCollection ProcessDatas { get; set; } = new ObservableCollection(); - - public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( - nameof(ItemsSource), - typeof(object), - typeof(AnalyticSummaryPopupViewModel), - new PropertyMetadata(default)); - - public object ItemsSource - { - get => (object)GetValue(ItemsSourceProperty); - set => SetValue(ItemsSourceProperty, value); - } - - public ProcessPerformanceTableControl() - { - this.InitializeComponent(); - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml deleted file mode 100644 index 4f875f45c2..0000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -