diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 63ad5e7ee0..a081d3fcd1 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1965,6 +1965,7 @@ Wwanpp XAxis xclip xcopy +XDeployment XDocument XElement xfd diff --git a/doc/devdocs/tools/bug-report-tool.md b/doc/devdocs/tools/bug-report-tool.md index f73bdf3fc3..aa2c3dc1ba 100644 --- a/doc/devdocs/tools/bug-report-tool.md +++ b/doc/devdocs/tools/bug-report-tool.md @@ -17,6 +17,7 @@ The bug report includes the following files: * `context-menu-packages.txt` - Information about the packages that are registered for the new Windows 11 context menu. * `dotnet-installation-info.txt` - Information about the installed .NET versions. * `EventViewer-*.xml` - These files contain event logs from the Windows Event Viewer for the executable specified in the file name. +* `EventViewer-Microsoft-Windows-AppXDeploymentServer/Operational.xml` - Contains event logs from the AppXDeployment-Server which are useful for diagnosing MSIX installation issues. * `gpo-configuration-info.txt` - Information about the configured [GPO](/doc/gpo/README.md). * `installationFolderStructure.txt` - Information about the folder structure of the installation. All lines with files have the following structure: `FileName Version MD5Hash`. * `last_version_run.json` - Information about the last version of PowerToys that was run. diff --git a/tools/BugReportTool/BugReportTool/EventViewer.cpp b/tools/BugReportTool/BugReportTool/EventViewer.cpp index f6e9a6baf0..549ceb90b4 100644 --- a/tools/BugReportTool/BugReportTool/EventViewer.cpp +++ b/tools/BugReportTool/BugReportTool/EventViewer.cpp @@ -23,7 +23,7 @@ namespace // Report last 30 days const long long PERIOD = 10 * 24 * 3600ll * 1000; - const std::wstring QUERY = L"" \ + const std::wstring QUERY_BY_PROCESS = L"" \ L" " \ L" " \ + L" *[System[TimeCreated[timediff(@SystemTime)<%I64u]]]" \ + L" " \ + L" " \ + L""; + + std::wstring GetQuery(std::wstring processName) { wchar_t buff[1000]; memset(buff, 0, sizeof(buff)); - _snwprintf_s(buff, sizeof(buff), QUERY.c_str(), PERIOD, processName.c_str()); + _snwprintf_s(buff, sizeof(buff), QUERY_BY_PROCESS.c_str(), PERIOD, processName.c_str()); + return buff; + } + + std::wstring GetQueryByChannel(std::wstring channelName) + { + wchar_t buff[1000]; + memset(buff, 0, sizeof(buff)); + _snwprintf_s(buff, sizeof(buff), QUERY_BY_CHANNEL.c_str(), channelName.c_str(), PERIOD); return buff; } std::wofstream report; EVT_HANDLE hResults; + bool isChannel; + + bool ShouldIncludeEvent(const std::wstring& eventXml) + { + if (!isChannel) + { + return true; // Include all events if no filtering + } + + // Check if the event contains PowerToys or CommandPalette + return (eventXml.find(L"PowerToys") != std::wstring::npos || + eventXml.find(L"CommandPalette") != std::wstring::npos); + } void PrintEvent(EVT_HANDLE hEvent) { @@ -75,6 +105,17 @@ namespace } } + // Apply filtering if needed + std::wstring eventContent(pRenderedContent); + if (!ShouldIncludeEvent(eventContent)) + { + if (pRenderedContent) + { + free(pRenderedContent); + } + return; // Skip this event + } + XmlDocumentEx doc; doc.LoadXml(pRenderedContent); std::wstring formattedXml = L""; @@ -130,17 +171,27 @@ namespace } public: - EventViewerReporter(const std::filesystem::path& tmpDir, std::wstring processName) + EventViewerReporter(const std::filesystem::path& tmpDir, std::wstring queryName, std::wstring fileName, bool isChannel) + :isChannel(isChannel) { - auto query = GetQuery(processName); + std::wstring query = L""; + if (isChannel) + { + query = GetQueryByChannel(queryName); + } + else + { + query = GetQuery(queryName); + } + auto reportPath = tmpDir; - reportPath.append(L"EventViewer-" + processName + L".xml"); + reportPath.append(L"EventViewer-" + fileName + L".xml"); report = std::wofstream(reportPath); - hResults = EvtQuery(NULL, NULL, GetQuery(processName).c_str(), EvtQueryChannelPath); + hResults = EvtQuery(NULL, NULL, query.c_str(), EvtQueryChannelPath); if (NULL == hResults) { - report << "Failed to report info for " << processName << ". " << get_last_error_or_default(GetLastError()) << std::endl; + report << "Failed to report info for " << queryName << ". " << get_last_error_or_default(GetLastError()) << std::endl; return; } } @@ -175,6 +226,11 @@ void EventViewer::ReportEventViewerInfo(const std::filesystem::path& tmpDir) { for (auto& process : processes) { - EventViewerReporter(tmpDir, process).Report(); + EventViewerReporter(tmpDir, process, process, false).Report(); } } + +void EventViewer::ReportAppXDeploymentLogs(const std::filesystem::path& tmpDir) +{ + EventViewerReporter(tmpDir, L"Microsoft-Windows-AppXDeploymentServer/Operational", L"AppXDeploymentServerEventLog", true).Report(); +} diff --git a/tools/BugReportTool/BugReportTool/EventViewer.h b/tools/BugReportTool/BugReportTool/EventViewer.h index 0d50f4253e..94176b4217 100644 --- a/tools/BugReportTool/BugReportTool/EventViewer.h +++ b/tools/BugReportTool/BugReportTool/EventViewer.h @@ -4,4 +4,5 @@ namespace EventViewer { void ReportEventViewerInfo(const std::filesystem::path& tmpDir); + void ReportAppXDeploymentLogs(const std::filesystem::path& tmpDir); } diff --git a/tools/BugReportTool/BugReportTool/Main.cpp b/tools/BugReportTool/BugReportTool/Main.cpp index a653c25d57..7716512125 100644 --- a/tools/BugReportTool/BugReportTool/Main.cpp +++ b/tools/BugReportTool/BugReportTool/Main.cpp @@ -381,6 +381,9 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) // Write event viewer logs info to the temporary folder EventViewer::ReportEventViewerInfo(reportDir); + // Write AppXDeployment-Server event logs to the temporary folder + EventViewer::ReportAppXDeploymentLogs(reportDir); + ReportInstallerLogs(tempDir, reportDir); ReportInstalledContextMenuPackages(reportDir);