Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 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 @@ -610,6 +611,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 @@

- 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

Check warning on line 342 in azure-pipelines.yml

View workflow job for this annotation

GitHub Actions / Check Spelling

`mdmpto` is not a recognized word. (unrecognized-spelling)
displayName: Run Unit Tests Unpackaged Under System Context
workingDirectory: '$(buildOutDir)\AppInstallerCLITests'
condition: succeededOrFailed()
Expand All @@ -353,7 +353,7 @@
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 @@
- 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 @@
[Parameter(Mandatory=$false)]
[string]$LogTarget,

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

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

Expand Down Expand Up @@ -93,6 +98,14 @@
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 @@
$Local:TestArgs = $Local:TestArgs + " -logto ""$LogTarget"""
}

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

Check warning on line 145 in src/AppInstallerCLITests/Run-TestsInPackage.ps1

View workflow job for this annotation

GitHub Actions / Check Spelling

`mdmpto` is not a recognized word. (unrecognized-spelling)
}

if (![String]::IsNullOrEmpty($TestResultsTarget))
{
$Local:TestArgs = $Local:TestArgs + " -s -r junit -o ""$TestResultsTarget"""
Expand Down
12 changes: 11 additions & 1 deletion 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 @@ -107,6 +108,15 @@
{
keepSQLLogging = true;
}
else if ("-mdmp"s == argv[i])
{
Debugging::EnableSelfInitiatedMinidump();
}
else if ("-mdmpto"s == argv[i])

Check warning on line 115 in src/AppInstallerCLITests/main.cpp

View workflow job for this annotation

GitHub Actions / Check Spelling

`mdmpto` is not a recognized word. (unrecognized-spelling)
{
++i;
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();
}
Loading