Report tool improvements (#8709)

* bugreport: move to tools

* bugreport: skip packaging installers, format time with seconds, remove monitor-info-report tool

* bugreport: move BugReportTool to Tools folder

* fix CI

* fix CDPX
This commit is contained in:
Andrey Nekrasov
2020-12-22 17:15:46 +03:00
committed by GitHub
parent 0843efd282
commit dde63b5017
19 changed files with 108 additions and 282 deletions

View File

@@ -0,0 +1,69 @@
<?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.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{99126840-5c30-4e9e-ac6c-e73dded5c3bd}</ProjectGuid>
<RootNamespace>BugReportTool</RootNamespace>
<ProjectName>BugReportTool</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<IntDir>$(SolutionDir)..\..\$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)..\..\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
</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" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>../../../src/</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\deps\cziplib\src\zip.c">
<WarningLevel>TurnOffAllWarnings</WarningLevel>
</ClCompile>
<ClCompile Include="ReportMonitorInfo.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="ZipTools\zipfolder.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\common\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\deps\cziplib\src\miniz.h" />
<ClInclude Include="..\..\..\deps\cziplib\src\zip.h" />
<ClInclude Include="ReportMonitorInfo.h" />
<ClInclude Include="..\..\..\common\utils\json.h" />
<ClInclude Include="ZipTools\zipfolder.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.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.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp" />
<ClCompile Include="ZipTools\zipfolder.cpp">
<Filter>ZipTools</Filter>
</ClCompile>
<ClCompile Include="..\..\..\deps\cziplib\src\zip.c" />
<ClCompile Include="ReportMonitorInfo.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="ZipTools">
<UniqueIdentifier>{3ae1b6aa-4134-47b1-afdf-dfb3b5901dcc}</UniqueIdentifier>
</Filter>
<Filter Include="MonitorReportTool">
<UniqueIdentifier>{83b7e7d9-49b7-4fc8-9853-9dbb8f2c0e76}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ZipTools\zipfolder.h">
<Filter>ZipTools</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\utils\json.h" />
<ClInclude Include="..\..\..\deps\cziplib\src\miniz.h" />
<ClInclude Include="..\..\..\deps\cziplib\src\zip.h" />
<ClInclude Include="ReportMonitorInfo.h" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,279 @@
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>
#include <Shlobj.h>
#include <winrt/Windows.Data.Json.h>
#include <winrt/Windows.Foundation.Collections.h>
#include "ZipTools/ZipFolder.h"
#include <common/SettingsAPI/settings_helpers.h>
#include <common/utils/json.h>
#include <common/utils/timeutil.h>
#include "ReportMonitorInfo.h"
using namespace std;
using namespace std::filesystem;
using namespace winrt::Windows::Data::Json;
map<wstring, vector<wstring>> escapeInfo = {
{ L"FancyZones\\app-zone-history.json", { L"app-zone-history/app-path" } },
{ L"PowerRename\\replace-mru.json", { L"MRUList" } },
{ L"PowerRename\\search-mru.json", { L"MRUList" } },
{ L"FancyZones\\settings.json", { L"properties/fancyzones_excluded_apps" } },
{ L"PowerToys Run\\Settings\\QueryHistory.json", { L"Items" } },
};
vector<wstring> filesToDelete = {
L"PowerToys Run\\Cache\\Image.cache"
};
vector<wstring> getXpathArray(wstring xpath)
{
vector<wstring> result;
wstring cur = L"";
for (auto ch : xpath)
{
if (ch == L'/')
{
result.push_back(cur);
cur = L"";
continue;
}
cur += ch;
}
if (!cur.empty())
{
result.push_back(cur);
}
return result;
}
void hideByXPath(IJsonValue& val, vector<wstring>& xpathArray, int p)
{
if (val.ValueType() == JsonValueType::Array)
{
for (auto it : val.GetArray())
{
hideByXPath(it, xpathArray, p);
}
return;
}
if (p == xpathArray.size() - 1)
{
if (val.ValueType() == JsonValueType::Object)
{
auto obj = val.GetObjectW();
if (obj.HasKey(xpathArray[p]))
{
auto privateDatavalue = JsonValue::CreateStringValue(L"<private_data>");
obj.SetNamedValue(xpathArray[p], privateDatavalue);
}
}
return;
}
if (val.ValueType() == JsonValueType::Object)
{
IJsonValue newVal;
try
{
newVal = val.GetObjectW().GetNamedValue(xpathArray[p]);
}
catch (...)
{
return;
}
hideByXPath(newVal, xpathArray, p + 1);
}
}
void hideForFile(const path& dir, const wstring& relativePath)
{
path jsonPath = dir;
jsonPath.append(relativePath);
auto jObject = json::from_file(jsonPath.wstring());
if (!jObject.has_value())
{
wprintf(L"Can not parse file %s\n", jsonPath.c_str());
return;
}
JsonValue jValue = json::value(jObject.value());
for (auto xpath : escapeInfo[relativePath])
{
vector<wstring> xpathArray = getXpathArray(xpath);
hideByXPath(jValue, xpathArray, 0);
}
json::to_file(jsonPath.wstring(), jObject.value());
}
bool del(wstring path)
{
error_code err;
remove_all(path, err);
if (err.value() != 0)
{
wprintf_s(L"Can not delete %s. Error code: %d", path.c_str(), err.value());
return false;
}
return true;
}
void hideUserPrivateInfo(const filesystem::path& dir)
{
// Replace data in json files
for (auto& it : escapeInfo)
{
hideForFile(dir, it.first);
}
// delete files
for (auto it : filesToDelete)
{
auto path = dir;
path = path.append(it);
del(path);
}
}
void reportMonitorInfo(const filesystem::path& tmpDir)
{
auto monitorReportPath = tmpDir;
monitorReportPath.append("monitor-report-info.txt");
try
{
wofstream monitorReport(monitorReportPath);
monitorReport << "GetSystemMetrics = " << GetSystemMetrics(SM_CMONITORS) << '\n';
report(monitorReport);
}
catch (std::exception& ex)
{
printf("Can not report monitor info. %s\n", ex.what());
}
catch (...)
{
printf("Can not report monitor info\n");
}
}
void reportWindowsVersion(const filesystem::path& tmpDir)
{
auto versionReportPath = tmpDir;
versionReportPath = versionReportPath.append("windows-version.txt");
OSVERSIONINFOEXW osInfo;
try
{
NTSTATUS(WINAPI * RtlGetVersion)
(LPOSVERSIONINFOEXW) = nullptr;
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
if (RtlGetVersion)
{
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
RtlGetVersion(&osInfo);
}
}
catch (...)
{
printf("Cannot get windows version info\n");
return;
}
try
{
wofstream versionReport(versionReportPath);
versionReport << "MajorVersion: " << osInfo.dwMajorVersion << endl;
versionReport << "MinorVersion: " << osInfo.dwMinorVersion << endl;
versionReport << "BuildNumber: " << osInfo.dwBuildNumber << endl;
}
catch(...)
{
printf("Can not write to %s", versionReportPath.string().c_str());
}
}
int wmain(int argc, wchar_t* argv[], wchar_t*)
{
// Get path to save zip
wstring saveZipPath;
if (argc > 1)
{
saveZipPath = argv[1];
}
else
{
wchar_t buffer[MAX_PATH];
if (SHGetSpecialFolderPath(HWND_DESKTOP, buffer, CSIDL_DESKTOP, FALSE))
{
saveZipPath = buffer;
}
else
{
printf("Can not retrieve a desktop path. Error code: %d", GetLastError());
}
}
auto powerToys = PTSettingsHelper::get_root_save_folder_location();
// Copy to a temp folder
auto tmpDir = temp_directory_path();
tmpDir = tmpDir.append("PowerToys\\");
powerToys = powerToys + L"\\";
if (!del(tmpDir))
{
return 1;
}
try
{
copy(powerToys, tmpDir, copy_options::recursive);
// Remove updates folder contents
del(tmpDir / "Updates");
}
catch (...)
{
printf("Copy PowerToys directory failed");
return 1;
}
// Hide sensitive information
hideUserPrivateInfo(tmpDir);
// Write monitors info to the temporary folder
reportMonitorInfo(tmpDir);
// Write windows version info to the temporary folder
reportWindowsVersion(tmpDir);
// Zip folder
auto zipPath = path::path(saveZipPath);
std::string reportFilename{"PowerToysReport_"};
reportFilename += timeutil::format_as_local("%F-%H-%M-%S", timeutil::now());
reportFilename += ".zip";
zipPath /= reportFilename;
try
{
zipFolder(zipPath, tmpDir);
}
catch (...)
{
printf("Zip folder failed");
return 1;
}
del(tmpDir);
return 0;
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include "ReportMonitorInfo.h"
#include <Windows.h>
#include "../../../src/common/utils/winapi_error.h"
int report(std::wostream& os)
{
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM prm) -> BOOL {
std::wostream& os = *(std::wostream*)prm;
MONITORINFOEX mi;
mi.cbSize = sizeof(mi);
if (GetMonitorInfo(monitor, &mi))
{
os << "GetMonitorInfo OK\n";
DISPLAY_DEVICE displayDevice = { sizeof(displayDevice) };
if (EnumDisplayDevices(mi.szDevice, 0, &displayDevice, 1))
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
{
os << "EnumDisplayDevices OK[MIRRORING_DRIVER]: \n"
<< "\tDeviceID = " << displayDevice.DeviceID << '\n'
<< "\tDeviceKey = " << displayDevice.DeviceKey << '\n'
<< "\tDeviceName = " << displayDevice.DeviceName << '\n'
<< "\tDeviceString = " << displayDevice.DeviceString << '\n';
}
else
{
os << "EnumDisplayDevices OK:\n"
<< "\tDeviceID = " << displayDevice.DeviceID << '\n'
<< "\tDeviceKey = " << displayDevice.DeviceKey << '\n'
<< "\tDeviceName = " << displayDevice.DeviceName << '\n'
<< "\tDeviceString = " << displayDevice.DeviceString << '\n';
}
}
else
{
auto message = get_last_error_message(GetLastError());
os << "EnumDisplayDevices FAILED: " << (message.has_value() ? message.value() : L"") << '\n';
}
}
else
{
auto message = get_last_error_message(GetLastError());
os << "GetMonitorInfo FAILED: " << (message.has_value() ? message.value() : L"") << '\n';
}
return TRUE;
};
if (EnumDisplayMonitors(nullptr, nullptr, callback, (LPARAM)&os))
{
os << "EnumDisplayMonitors OK\n";
}
else
{
auto message = get_last_error_message(GetLastError());
os << "EnumDisplayMonitors FAILED: " << (message.has_value() ? message.value() : L"") << '\n';
}
return 0;
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include <fstream>
int report(std::wostream& os);

View File

@@ -0,0 +1,28 @@
#include "zipfolder.h"
#include "..\..\..\..\deps\cziplib\src\zip.h"
void zipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath)
{
struct zip_t* zip = zip_open(zipPath.string().c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
if (!zip)
{
printf("Can not open zip.");
throw -1;
}
using recursive_directory_iterator = std::filesystem::recursive_directory_iterator;
const size_t rootSize = folderPath.wstring().size();
for (const auto& dirEntry : recursive_directory_iterator(folderPath))
{
if (dirEntry.is_regular_file())
{
auto path = dirEntry.path().string();
auto relativePath = path.substr(rootSize, path.size());
zip_entry_open(zip, relativePath.c_str());
zip_entry_fwrite(zip, path.c_str());
zip_entry_close(zip);
}
}
zip_close(zip);
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include <filesystem>
void zipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath);

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
</packages>