mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
[General]Add an option for telemetry opt-in and visualization(#34078)
* Data diagnostics opt-in
* [c++] Drop DROP_PII flag
* Bump telemtry package to 2.0.2
* Drop DropPii from custom actions
* Cleanup
* Do not start manually C# EtwTrace. FZ engine exit event.
* ImageResizer, PowerRename, FileLocksmith prev handlers
* Revert C# handlers exe logging
* Revert "Revert C# handlers exe logging"
This reverts commit 4c75a3953b.
* Do not recreate EtwTrace
* consume package
* xaml formatting
* Fix deps.json audit
* Update telem package paths
* Address PR comments
* Fix AdvancedPaste close on PT close
* Override etl file name for explorer loaded dlls
Start/stop tracer when needed for explorer loaded dlls to prevent explorer overload
* Fix setting desc
* Fix missing events
* Add infobar to restart when enable data viewing
* Flush on timer every 30s
* [Settings] Update View Data diagnostic description text
[New+] Add tracer
* Show Restart info bar for both enable/disable data viewer
* Fix newplus
* Fix stuck on restart and terminate AdvPaste exe on destroy()
* [Installer] Add tracer
* Address PR comment
* Add missing tracers
* Exclude etw dir from BugReport
* Fix bad merge
* [Hosts] Proper exit on initial dialog
* [OOBE] Make Data diagnostic setting visible without scroll
* [OOBE] Add hiperlynk to open general settings
* Disable data view on disabling data diagnostics
* Don't disable View data button
* Fix disabling data viewing
* Add missing dot
* Revert formatting
This commit is contained in:
310
src/common/Telemetry/EtwTrace/EtwTrace.cpp
Normal file
310
src/common/Telemetry/EtwTrace/EtwTrace.cpp
Normal file
@@ -0,0 +1,310 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
#include "ETWTrace.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <wil\stl.h>
|
||||
#include <wil\win32_helpers.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
|
||||
constexpr inline const wchar_t* ViewDataDiagnosticsRegValueName = L"DataDiagnosticsViewEnabled";
|
||||
|
||||
inline std::wstring get_root_save_folder_location()
|
||||
{
|
||||
PWSTR local_app_path;
|
||||
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
|
||||
std::wstring result{ local_app_path };
|
||||
CoTaskMemFree(local_app_path);
|
||||
|
||||
result += L"\\Microsoft\\PowerToys";
|
||||
std::filesystem::path save_path(result);
|
||||
if (!std::filesystem::exists(save_path))
|
||||
{
|
||||
std::filesystem::create_directories(save_path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsDataDiagnosticsEnabled()
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
0,
|
||||
KEY_READ,
|
||||
&key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD isDataDiagnosticsEnabled = 0;
|
||||
DWORD size = sizeof(isDataDiagnosticsEnabled);
|
||||
|
||||
if (RegGetValueW(
|
||||
HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
DataDiagnosticsRegValueName,
|
||||
RRF_RT_REG_DWORD,
|
||||
nullptr,
|
||||
&isDataDiagnosticsEnabled,
|
||||
&size) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
return false;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
|
||||
return isDataDiagnosticsEnabled;
|
||||
}
|
||||
|
||||
bool isViewDataDiagnosticEnabled()
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
0,
|
||||
KEY_READ,
|
||||
&key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD isDataDiagnosticsEnabled = 0;
|
||||
DWORD size = sizeof(isDataDiagnosticsEnabled);
|
||||
|
||||
if (RegGetValueW(
|
||||
HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
ViewDataDiagnosticsRegValueName,
|
||||
RRF_RT_REG_DWORD,
|
||||
nullptr,
|
||||
&isDataDiagnosticsEnabled,
|
||||
&size) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
return false;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
|
||||
return isDataDiagnosticsEnabled == 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Shared
|
||||
{
|
||||
namespace Trace
|
||||
{
|
||||
ETWTrace::ETWTrace()
|
||||
{
|
||||
GUID id;
|
||||
if (SUCCEEDED(CLSIDFromString(PowerToysProviderGUID, &id)))
|
||||
{
|
||||
m_providerGUID = id;
|
||||
}
|
||||
|
||||
fs::path outputFolder = get_root_save_folder_location();
|
||||
m_etwFolder = (outputFolder / c_etwFolderName);
|
||||
}
|
||||
|
||||
ETWTrace::ETWTrace(const std::wstring& etlFileNameOverride) :
|
||||
ETWTrace()
|
||||
{
|
||||
m_etlFileNameOverride = etlFileNameOverride;
|
||||
}
|
||||
|
||||
ETWTrace::~ETWTrace()
|
||||
{
|
||||
Flush();
|
||||
Stop();
|
||||
m_etwFolder.clear();
|
||||
m_providerGUID = {};
|
||||
}
|
||||
|
||||
void ETWTrace::UpdateState(bool tracing)
|
||||
{
|
||||
if (tracing)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ETWTrace::Flush()
|
||||
{
|
||||
if (m_tracing)
|
||||
{
|
||||
Control(EVENT_TRACE_CONTROL_FLUSH);
|
||||
// Control(EVENT_TRACE_CONTROL_INCREMENT_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
void ETWTrace::CreateEtwFolderIfNeeded()
|
||||
{
|
||||
if (!std::filesystem::exists(m_etwFolder))
|
||||
{
|
||||
std::filesystem::create_directories(m_etwFolder);
|
||||
}
|
||||
else if (!std::filesystem::is_directory(m_etwFolder))
|
||||
{
|
||||
std::filesystem::remove(m_etwFolder);
|
||||
std::filesystem::create_directory(m_etwFolder);
|
||||
}
|
||||
|
||||
THROW_HR_IF(E_UNEXPECTED, !std::filesystem::exists(m_etwFolder));
|
||||
}
|
||||
|
||||
void ETWTrace::InitEventTraceProperties()
|
||||
{
|
||||
const std::filesystem::path exePath(wil::GetModuleFileNameW<std::wstring>(nullptr));
|
||||
const auto exeName = exePath.stem().wstring();
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto timeNow = std::chrono::system_clock::to_time_t(now);
|
||||
std::wstringstream dateTime;
|
||||
struct tm timeInfo
|
||||
{
|
||||
};
|
||||
errno_t err = localtime_s(&timeInfo, &timeNow);
|
||||
if (err == 0)
|
||||
{
|
||||
dateTime << std::put_time(&timeInfo, L"-%m-%d-%Y__%H_%M_%S");
|
||||
}
|
||||
|
||||
if (m_etlFileNameOverride.empty())
|
||||
{
|
||||
m_sessionName = wil::str_printf<std::wstring>(L"%ws-%d%ws", exeName.c_str(), GetCurrentProcessId(), dateTime.str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sessionName = wil::str_printf<std::wstring>(L"%ws-%d%ws", m_etlFileNameOverride.c_str(), GetCurrentProcessId(), dateTime.str().c_str());
|
||||
}
|
||||
|
||||
std::replace(m_sessionName.begin(), m_sessionName.end(), '.', '_');
|
||||
|
||||
const ULONG etwSessionNameCharCount = static_cast<ULONG>(m_sessionName.size() + 1);
|
||||
const ULONG etwSessionNameByteSize = etwSessionNameCharCount * sizeof(m_sessionName[0]);
|
||||
|
||||
auto etlFileNameFormattedCounter = m_sessionName + c_etwNewFileFormattedCounter;
|
||||
std::filesystem::path etlFilePath = m_etwFolder / etlFileNameFormattedCounter;
|
||||
etlFilePath.replace_extension(c_etwFileNameEnd);
|
||||
THROW_HR_IF(E_UNEXPECTED, etlFilePath.empty());
|
||||
|
||||
const auto etlFilePathStr = etlFilePath.wstring();
|
||||
// std::string/wstring returns number of characters not including the null terminator, so add +1 for that.
|
||||
const ULONG etwFilePathCharCount = static_cast<ULONG>(etlFilePathStr.size() + 1);
|
||||
const ULONG etwFilePathByteSize = etwFilePathCharCount * sizeof(etlFilePathStr[0]);
|
||||
|
||||
const ULONG bufferSizeInBytes = sizeof(EVENT_TRACE_PROPERTIES) + etwSessionNameByteSize + etwFilePathByteSize;
|
||||
auto eventTracePropertiesBuffer = std::make_unique<unsigned char[]>(bufferSizeInBytes);
|
||||
ZeroMemory(eventTracePropertiesBuffer.get(), bufferSizeInBytes);
|
||||
auto eventTraceProperties = reinterpret_cast<EVENT_TRACE_PROPERTIES*>(eventTracePropertiesBuffer.get());
|
||||
|
||||
eventTraceProperties->Wnode.BufferSize = bufferSizeInBytes;
|
||||
eventTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
||||
eventTraceProperties->Wnode.ClientContext = 1;
|
||||
eventTraceProperties->Wnode.Guid = m_providerGUID;
|
||||
eventTraceProperties->BufferSize = 4; // 4KB, the minimum size
|
||||
eventTraceProperties->LogFileMode = EVENT_TRACE_PRIVATE_LOGGER_MODE | EVENT_TRACE_PRIVATE_IN_PROC | EVENT_TRACE_FILE_MODE_NEWFILE;
|
||||
eventTraceProperties->MaximumFileSize = 1; // 1 MB
|
||||
|
||||
// LoggerName is placed at the end of EVENT_TRACE_PROPERTIES structure
|
||||
eventTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
||||
wcsncpy_s(reinterpret_cast<LPWSTR>(eventTracePropertiesBuffer.get() + eventTraceProperties->LoggerNameOffset), etwSessionNameCharCount, m_sessionName.c_str(), etwSessionNameCharCount);
|
||||
|
||||
// LogFileName is placed at the end of the Logger Name
|
||||
eventTraceProperties->LogFileNameOffset = eventTraceProperties->LoggerNameOffset + etwSessionNameByteSize;
|
||||
wcsncpy_s(reinterpret_cast<LPWSTR>(eventTracePropertiesBuffer.get() + eventTraceProperties->LogFileNameOffset), etwFilePathCharCount, etlFilePathStr.c_str(), etwFilePathCharCount);
|
||||
|
||||
m_eventTracePropertiesBuffer = std::move(eventTracePropertiesBuffer);
|
||||
}
|
||||
|
||||
void ETWTrace::Start()
|
||||
{
|
||||
if (m_tracing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDataDiagnosticsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isViewDataDiagnosticEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateEtwFolderIfNeeded();
|
||||
InitEventTraceProperties();
|
||||
|
||||
auto eventTraceProperties = reinterpret_cast<EVENT_TRACE_PROPERTIES*>(m_eventTracePropertiesBuffer.get());
|
||||
THROW_IF_WIN32_ERROR(StartTrace(&m_traceHandle, m_sessionName.c_str(), eventTraceProperties));
|
||||
Enable(EVENT_CONTROL_CODE_ENABLE_PROVIDER);
|
||||
|
||||
m_tracing = true;
|
||||
|
||||
m_flushing_thread = std::thread([this] { FlushWorker(); });
|
||||
}
|
||||
|
||||
void ETWTrace::Stop()
|
||||
{
|
||||
if (!m_tracing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Enable(EVENT_CONTROL_CODE_DISABLE_PROVIDER);
|
||||
|
||||
// ControlTrace with EVENT_TRACE_CONTROL_STOP on the trace handle,
|
||||
// which is equivalent to calling CloseTrace() on the trace handle.
|
||||
Control(EVENT_TRACE_CONTROL_STOP);
|
||||
|
||||
m_traceHandle = INVALID_PROCESSTRACE_HANDLE;
|
||||
m_eventTracePropertiesBuffer.reset();
|
||||
m_tracing = false;
|
||||
m_terminate_flushing_thread.notify_one();
|
||||
m_flushing_thread.join();
|
||||
}
|
||||
|
||||
void ETWTrace::Control(ULONG traceControlCode)
|
||||
{
|
||||
auto eventTraceProperties = reinterpret_cast<EVENT_TRACE_PROPERTIES*>(m_eventTracePropertiesBuffer.get());
|
||||
const ULONG result = ControlTrace(m_traceHandle, m_sessionName.c_str(), eventTraceProperties, traceControlCode);
|
||||
THROW_IF_FAILED(HRESULT_FROM_WIN32(result));
|
||||
}
|
||||
|
||||
void ETWTrace::Enable(ULONG eventControlCode)
|
||||
{
|
||||
// Control the main provider
|
||||
THROW_IF_WIN32_ERROR(EnableTraceEx2(m_traceHandle, &m_providerGUID, eventControlCode, TRACE_LEVEL_VERBOSE, 0, 0, 0, nullptr));
|
||||
}
|
||||
|
||||
void ETWTrace::FlushWorker()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while (m_tracing)
|
||||
{
|
||||
m_terminate_flushing_thread.wait_for(lock,
|
||||
std::chrono::seconds(30),
|
||||
[this]() { return !m_tracing.load(); });
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/common/Telemetry/EtwTrace/EtwTrace.h
Normal file
54
src/common/Telemetry/EtwTrace/EtwTrace.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
#include <evntrace.h>
|
||||
#include <filesystem>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
|
||||
namespace Shared
|
||||
{
|
||||
namespace Trace
|
||||
{
|
||||
class ETWTrace
|
||||
{
|
||||
public:
|
||||
static inline const wchar_t* PowerToysProviderGUID = L"{38e8889b-9731-53f5-e901-e8a7c1753074}";
|
||||
|
||||
ETWTrace();
|
||||
ETWTrace(const std::wstring& etlFileNameOverride);
|
||||
~ETWTrace();
|
||||
|
||||
void UpdateState(bool tracing);
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
void CreateEtwFolderIfNeeded();
|
||||
void InitEventTraceProperties();
|
||||
void Start();
|
||||
void Stop();
|
||||
void Control(const ULONG traceControlCode);
|
||||
void Enable(const ULONG eventControlCode);
|
||||
void FlushWorker();
|
||||
|
||||
GUID m_providerGUID{};
|
||||
std::filesystem::path m_etwFolder;
|
||||
std::wstring m_sessionName;
|
||||
TRACEHANDLE m_traceHandle{ INVALID_PROCESSTRACE_HANDLE };
|
||||
std::unique_ptr<unsigned char[]> m_eventTracePropertiesBuffer;
|
||||
std::atomic_bool m_tracing{ false };
|
||||
std::wstring m_etlFileNameOverride{};
|
||||
std::thread m_flushing_thread;
|
||||
std::condition_variable m_terminate_flushing_thread;
|
||||
std::mutex m_mutex;
|
||||
|
||||
static constexpr PCWSTR c_etwFolderName = L"etw";
|
||||
static constexpr PCWSTR c_etwNewFileFormattedCounter = L"-%d";
|
||||
static constexpr PCWSTR c_etwFileNameEnd = L".etl";
|
||||
};
|
||||
}
|
||||
}
|
||||
51
src/common/Telemetry/EtwTrace/EtwTrace.vcxproj
Normal file
51
src/common/Telemetry/EtwTrace/EtwTrace.vcxproj
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{8f021b46-362b-485c-bfba-ccf83e820cbd}</ProjectGuid>
|
||||
<RootNamespace>EtwTrace</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EtwTrace.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EtwTrace.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
39
src/common/Telemetry/EtwTrace/EtwTrace.vcxproj.filters
Normal file
39
src/common/Telemetry/EtwTrace/EtwTrace.vcxproj.filters
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EtwTrace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EtwTrace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
5
src/common/Telemetry/EtwTrace/packages.config
Normal file
5
src/common/Telemetry/EtwTrace/packages.config
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
5
src/common/Telemetry/EtwTrace/pch.cpp
Normal file
5
src/common/Telemetry/EtwTrace/pch.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
23
src/common/Telemetry/EtwTrace/pch.h
Normal file
23
src/common/Telemetry/EtwTrace/pch.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <ShlObj.h>
|
||||
#include <sstream>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include <winrt/base.h>
|
||||
|
||||
#endif //PCH_H
|
||||
63
src/common/Telemetry/TraceBase.h
Normal file
63
src/common/Telemetry/TraceBase.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "ProjectTelemetry.h"
|
||||
|
||||
#define TraceLoggingWriteWrapper(provider, eventName, ...) \
|
||||
if (IsDataDiagnosticsEnabled()) \
|
||||
{ \
|
||||
TraceLoggingWrite(provider, eventName, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
namespace telemetry
|
||||
{
|
||||
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
|
||||
|
||||
class TraceBase
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider()
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
static void UnregisterProvider()
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
static bool IsDataDiagnosticsEnabled()
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
0,
|
||||
KEY_READ,
|
||||
&key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD isDataDiagnosticsEnabled = 0;
|
||||
DWORD size = sizeof(isDataDiagnosticsEnabled);
|
||||
|
||||
if (RegGetValueW(
|
||||
HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
DataDiagnosticsRegValueName,
|
||||
RRF_RT_REG_DWORD,
|
||||
nullptr,
|
||||
&isDataDiagnosticsEnabled,
|
||||
&size) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
return false;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
|
||||
return isDataDiagnosticsEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace telemetry
|
||||
Reference in New Issue
Block a user