Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ ERRORONEXIT
errstr
ESRB
etl
evtx
ewgp
ewgs
execustom
Expand Down Expand Up @@ -320,6 +321,7 @@ MBH
MBs
mday
mdmp
mdmpto
MDs
megamorf
microsoftentraid
Expand Down Expand Up @@ -610,6 +612,7 @@ wincodec
windir
windowsdeveloper
winerror
winevt
wingdi
wingetconfigroot
wingetcreate
Expand Down
32 changes: 30 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ jobs:

- pwsh: |
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
PsExec -accepteula -s -i $(buildOutDir)\AppInstallerCLITests\AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml
PsExec -accepteula -s -i $(buildOutDir)\AppInstallerCLITests\AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -mdmpto $(artifactsDir)\AICLI-Unpackaged-System.mdmp -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml
displayName: Run Unit Tests Unpackaged Under System Context
workingDirectory: '$(buildOutDir)\AppInstallerCLITests'
condition: succeededOrFailed()
Expand All @@ -353,7 +353,7 @@ jobs:
displayName: Run Unit Tests Packaged
inputs:
filePath: 'src\AppInstallerCLITests\Run-TestsInPackage.ps1'
arguments: '-Args "~[pips]" -BuildRoot $(buildOutDir) -PackageRoot $(packageLayoutDir) -LogTarget $(artifactsDir)\AICLI-Packaged.log -TestResultsTarget $(artifactsDir)\TEST-AppInstallerCLI-Packaged.xml -ScriptWait'
arguments: '-Args "~[pips]" -BuildRoot $(buildOutDir) -PackageRoot $(packageLayoutDir) -LogTarget $(artifactsDir)\AICLI-Packaged.log -MdmpTarget $(artifactsDir)\AICLI-Packaged.mdmp -TestResultsTarget $(artifactsDir)\TEST-AppInstallerCLI-Packaged.xml -ScriptWait'
workingDirectory: 'src'
condition: succeededOrFailed()

Expand Down Expand Up @@ -481,6 +481,34 @@ jobs:
- powershell: Get-Process LocalhostWebServer | Stop-Process
displayName: Stop LocalhostWebServer
condition: succeededOrFailed()

- task: PowerShell@2
displayName: 'Copy GA WinGet Log to artifacts folder'
inputs:
targetType: 'inline'
script: |
$source = "$env:LocalAppData\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir"
$destination = "$(artifactsDir)\GA_WinGet_Logs"
if (Test-Path $source) {
Copy-Item -Path $source -Destination $destination -Recurse -Force
} else {
Write-Host "WinGet logs not found at $source"
}
condition: succeededOrFailed()

- task: PowerShell@2
displayName: 'Copy Application Event Logs to Artifacts'
inputs:
targetType: 'inline'
script: |
$source = "$env:SystemRoot\System32\winevt\Logs\Application.evtx"
$destination = "$(artifactsDir)\Application.evtx"
if (Test-Path $source) {
Copy-Item -Path $source -Destination $destination -Force
} else {
Write-Host "Application event log not found at $source"
}
condition: succeededOrFailed()

- task: PublishPipelineArtifact@1
displayName: Publish Pipeline Artifacts
Expand Down
22 changes: 22 additions & 0 deletions src/AppInstallerCLITests/Run-TestsInPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
location relative to this script.
.PARAMETER LogTarget
The file path to log to.
.PARAMETER MdmpTarget
The path to write a minidump to if the tests crash.
.PARAMETER TestResultsTarget
The file path to place the test result file in.
.PARAMETER Args
Expand All @@ -31,6 +33,9 @@ param(
[Parameter(Mandatory=$false)]
[string]$LogTarget,

[Parameter(Mandatory=$false)]
[string]$MdmpTarget,

[Parameter(Mandatory=$false)]
[string]$TestResultsTarget,

Expand Down Expand Up @@ -93,6 +98,14 @@ if (![String]::IsNullOrEmpty($LogTarget))
Write-Host "Using LogTarget = $LogTarget"
}

if (![String]::IsNullOrEmpty($MdmpTarget))
{
$Local:temp = Split-Path -Parent $MdmpTarget
$Local:temp = Resolve-Path $Local:temp
$MdmpTarget = Join-Path $Local:temp (Split-Path -Leaf $MdmpTarget)
Write-Host "Using MdmpTarget = $MdmpTarget"
}

if (![String]::IsNullOrEmpty($TestResultsTarget))
{
$Local:temp = Split-Path -Parent $TestResultsTarget
Expand Down Expand Up @@ -123,6 +136,15 @@ else
$Local:TestArgs = $Local:TestArgs + " -logto ""$LogTarget"""
}

if ([String]::IsNullOrEmpty($MdmpTarget))
{
$Local:TestArgs = $Local:TestArgs + " -mdmp"
}
else
{
$Local:TestArgs = $Local:TestArgs + " -mdmpto ""$MdmpTarget"""
}

if (![String]::IsNullOrEmpty($TestResultsTarget))
{
$Local:TestArgs = $Local:TestArgs + " -s -r junit -o ""$TestResultsTarget"""
Expand Down
23 changes: 18 additions & 5 deletions src/AppInstallerCLITests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include <AppInstallerLogging.h>
#include <AppInstallerFileLogger.h>
#include <Public/AppInstallerTelemetry.h>
#include <Telemetry/TraceLogging.h>
#include <Telemetry/TraceLogging.h>
#include <winget/Debugging.h>
#include "TestCommon.h"
#include "TestSettings.h"

Expand Down Expand Up @@ -87,13 +88,14 @@ int main(int argc, char** argv)
}
else if ("-logto"s == argv[i])
{
++i;
Logging::FileLogger::Add(std::filesystem::path{ argv[i] });
if (++i < argc)
{
Logging::FileLogger::Add(std::filesystem::path{ argv[i] });
}
}
else if ("-tdd"s == argv[i])
{
++i;
if (i < argc)
if (++i < argc)
{
TestCommon::TestDataFile::SetTestDataBasePath(argv[i]);
hasSetTestDataBasePath = true;
Expand All @@ -107,6 +109,17 @@ int main(int argc, char** argv)
{
keepSQLLogging = true;
}
else if ("-mdmp"s == argv[i])
{
Debugging::EnableSelfInitiatedMinidump();
}
else if ("-mdmpto"s == argv[i])
{
if (++i < argc)
{
Debugging::EnableSelfInitiatedMinidump(std::filesystem::path{ argv[i] });
}
}
else
{
args.push_back(argv[i]);
Expand Down
49 changes: 34 additions & 15 deletions src/AppInstallerCommonCore/Debugging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,7 @@ namespace AppInstaller::Debugging

struct SelfInitiatedMinidumpHelper
{
SelfInitiatedMinidumpHelper() : m_keepFile(false)
{
m_filePath = Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation);
m_filePath /= c_minidumpPrefix.data() + ('-' + Utility::GetCurrentTimeForFilename() + c_minidumpExtension.data());

m_file.reset(CreateFile(m_filePath.wstring().c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
THROW_LAST_ERROR_IF(!m_file);

SetUnhandledExceptionFilter(UnhandledExceptionCallback);
}
SelfInitiatedMinidumpHelper() = default;

~SelfInitiatedMinidumpHelper()
{
Expand Down Expand Up @@ -57,6 +47,30 @@ namespace AppInstaller::Debugging
return EXCEPTION_CONTINUE_SEARCH;
}

SelfInitiatedMinidumpHelper& Enable(const std::filesystem::path& filePath = {})
{
std::call_once(m_enableFlag, [&]()
{
if (filePath.empty())
{
m_filePath = Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation);
m_filePath /= c_minidumpPrefix.data() + ('-' + Utility::GetCurrentTimeForFilename() + c_minidumpExtension.data());
}
else
{
m_filePath = filePath;
}

m_file.reset(CreateFile(m_filePath.wstring().c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
THROW_LAST_ERROR_IF(!m_file);

SetUnhandledExceptionFilter(UnhandledExceptionCallback);
});

return *this;
}

void WriteMinidump()
{
std::thread([&]() {
Expand All @@ -66,20 +80,25 @@ namespace AppInstaller::Debugging
}

private:
std::once_flag m_enableFlag;
std::filesystem::path m_filePath;
wil::unique_handle m_file;
std::atomic_bool m_keepFile;
std::atomic_bool m_keepFile{ false };
};
}

void EnableSelfInitiatedMinidump()
{
// Force object creation and thus enabling of the crash detection.
SelfInitiatedMinidumpHelper::Instance();
SelfInitiatedMinidumpHelper::Instance().Enable();
}

void EnableSelfInitiatedMinidump(const std::filesystem::path& filePath)
{
SelfInitiatedMinidumpHelper::Instance().Enable(filePath);
}

void WriteMinidump()
{
SelfInitiatedMinidumpHelper::Instance().WriteMinidump();
SelfInitiatedMinidumpHelper::Instance().Enable().WriteMinidump();
}
}
7 changes: 7 additions & 0 deletions src/AppInstallerCommonCore/Public/winget/Debugging.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <filesystem>

namespace AppInstaller::Debugging
{
// Enables a self initiated minidump on certain process level failures.
// Only the first call to EnableSelfInitiatedMinidump has any effect.
void EnableSelfInitiatedMinidump();

// Enables a self initiated minidump on certain process level failures.
// Creates the minidump in the given location.
// Only the first call to EnableSelfInitiatedMinidump has any effect.
void EnableSelfInitiatedMinidump(const std::filesystem::path& filePath);

// Forces the minidump to be written.
void WriteMinidump();
}