Overview
The Windows Package Manager COM API uses a combination of status enums, HRESULT codes, and result information to report errors. Proper error handling ensures robust applications and helpful user feedback.Error Patterns
Package Management Errors
Package operations return result objects with status enums and extended error codes:public class InstallResult
{
InstallResultStatus Status { get; }
HRESULT ExtendedErrorCode { get; }
UInt32 InstallerErrorCode { get; } // When Status == InstallError
String CorrelationData { get; }
Boolean RebootRequired { get; }
}
Configuration Errors
Configuration operations useIConfigurationUnitResultInformation:
public interface IConfigurationUnitResultInformation
{
HRESULT ResultCode { get; }
String Description { get; }
String Details { get; }
ConfigurationUnitResultSource ResultSource { get; }
}
Package Management Error Handling
Install Errors
var result = await manager.InstallPackageAsync(package, options);
switch (result.Status)
{
case InstallResultStatus.Ok:
Console.WriteLine("Installation successful");
if (result.RebootRequired)
{
Console.WriteLine("Please reboot to complete installation");
}
break;
case InstallResultStatus.InstallError:
Console.WriteLine("Installer failed");
Console.WriteLine($"Extended Error: 0x{result.ExtendedErrorCode:X8}");
Console.WriteLine($"Installer Error Code: 0x{result.InstallerErrorCode:X}");
// Common installer error codes
switch (result.InstallerErrorCode)
{
case 0x80070005: // E_ACCESSDENIED
Console.WriteLine("Access denied. Run as administrator.");
break;
case 0x80070643: // ERROR_INSTALL_FAILURE
Console.WriteLine("Installation failed. Check installer logs.");
break;
case 0x80070BC9: // ERROR_SUCCESS_REBOOT_REQUIRED
Console.WriteLine("Installation requires reboot.");
break;
}
break;
case InstallResultStatus.DownloadError:
Console.WriteLine("Failed to download installer");
Console.WriteLine($"Error: 0x{result.ExtendedErrorCode:X8}");
// Check network connectivity
if (result.ExtendedErrorCode == unchecked((int)0x80072EFD)) // WININET_E_CANNOT_CONNECT
{
Console.WriteLine("Cannot connect to server. Check network.");
}
break;
case InstallResultStatus.BlockedByPolicy:
Console.WriteLine("Installation blocked by group policy");
break;
case InstallResultStatus.PackageAgreementsNotAccepted:
Console.WriteLine("Package agreements not accepted");
Console.WriteLine("Set AcceptPackageAgreements = true");
break;
case InstallResultStatus.NoApplicableInstallers:
Console.WriteLine("No installer available for this system");
Console.WriteLine("Check architecture and OS version requirements");
break;
case InstallResultStatus.InvalidOptions:
Console.WriteLine("Invalid install options provided");
break;
case InstallResultStatus.CatalogError:
Console.WriteLine("Catalog error occurred");
Console.WriteLine($"Error: 0x{result.ExtendedErrorCode:X8}");
break;
case InstallResultStatus.InternalError:
Console.WriteLine("Internal error occurred");
Console.WriteLine($"Error: 0x{result.ExtendedErrorCode:X8}");
break;
case InstallResultStatus.ManifestError:
Console.WriteLine("Package manifest error");
break;
}
Uninstall Errors
var result = await manager.UninstallPackageAsync(package, options);
switch (result.Status)
{
case UninstallResultStatus.Ok:
Console.WriteLine("Uninstallation successful");
break;
case UninstallResultStatus.UninstallError:
Console.WriteLine("Uninstaller failed");
Console.WriteLine($"Error Code: 0x{result.UninstallerErrorCode:X}");
Console.WriteLine($"HRESULT: 0x{result.ExtendedErrorCode:X8}");
break;
case UninstallResultStatus.BlockedByPolicy:
Console.WriteLine("Uninstall blocked by policy");
break;
case UninstallResultStatus.CatalogError:
Console.WriteLine("Catalog error");
break;
case UninstallResultStatus.InternalError:
Console.WriteLine("Internal error");
break;
case UninstallResultStatus.InvalidOptions:
Console.WriteLine("Invalid options");
break;
case UninstallResultStatus.ManifestError:
Console.WriteLine("Manifest error");
break;
}
Catalog Errors
// Connection errors
var connectResult = await catalogRef.ConnectAsync();
if (connectResult.Status != ConnectResultStatus.Ok)
{
switch (connectResult.Status)
{
case ConnectResultStatus.CatalogError:
Console.WriteLine("Failed to connect to catalog");
Console.WriteLine($"Error: 0x{connectResult.ExtendedErrorCode:X8}");
break;
case ConnectResultStatus.SourceAgreementsNotAccepted:
Console.WriteLine("Source agreements not accepted");
Console.WriteLine("Set AcceptSourceAgreements = true");
break;
}
return;
}
// Search errors
var findResult = await catalog.FindPackagesAsync(options);
if (findResult.Status != FindPackagesResultStatus.Ok)
{
switch (findResult.Status)
{
case FindPackagesResultStatus.CatalogError:
Console.WriteLine("Catalog error during search");
break;
case FindPackagesResultStatus.BlockedByPolicy:
Console.WriteLine("Search blocked by policy");
break;
case FindPackagesResultStatus.InvalidOptions:
Console.WriteLine("Invalid search options");
break;
case FindPackagesResultStatus.InternalError:
Console.WriteLine("Internal error");
break;
case FindPackagesResultStatus.AuthenticationError:
Console.WriteLine("Authentication failed");
Console.WriteLine("Check authentication credentials");
break;
case FindPackagesResultStatus.AccessDenied:
Console.WriteLine("Access denied to catalog");
break;
}
Console.WriteLine($"Extended Error: 0x{findResult.ExtendedErrorCode:X8}");
}
Configuration Error Handling
Opening Configuration Sets
var openResult = await processor.OpenConfigurationSetAsync(stream);
if (openResult.ResultCode != 0)
{
Console.WriteLine("Failed to open configuration:");
Console.WriteLine($" HRESULT: 0x{openResult.ResultCode:X8}");
if (!string.IsNullOrEmpty(openResult.Field))
{
Console.WriteLine($" Field: {openResult.Field}");
}
if (!string.IsNullOrEmpty(openResult.Value))
{
Console.WriteLine($" Value: {openResult.Value}");
}
if (openResult.Line > 0)
{
Console.WriteLine($" Location: Line {openResult.Line}, Column {openResult.Column}");
}
// Common YAML parsing errors
switch (openResult.ResultCode)
{
case unchecked((int)0x80070002): // ERROR_FILE_NOT_FOUND
Console.WriteLine("Configuration file not found");
break;
case unchecked((int)0x8007007B): // ERROR_INVALID_NAME
Console.WriteLine("Invalid YAML syntax");
break;
}
return;
}
var configSet = openResult.Set;
Apply Configuration Errors
var applyResult = await processor.ApplySetAsync(
configSet,
ApplyConfigurationSetFlags.None
);
if (applyResult.ResultCode != 0)
{
Console.WriteLine($"Configuration apply failed: 0x{applyResult.ResultCode:X8}");
}
foreach (var unitResult in applyResult.UnitResults)
{
var unit = unitResult.Unit;
if (unitResult.State == ConfigurationUnitState.Completed)
{
var result = unitResult.ResultInformation;
if (result.ResultCode != 0)
{
Console.WriteLine($"\nUnit failed: {unit.Type}");
Console.WriteLine($" Identifier: {unit.Identifier}");
Console.WriteLine($" HRESULT: 0x{result.ResultCode:X8}");
Console.WriteLine($" Description: {result.Description}");
Console.WriteLine($" Details: {result.Details}");
Console.WriteLine($" Source: {result.ResultSource}");
switch (result.ResultSource)
{
case ConfigurationUnitResultSource.Internal:
Console.WriteLine(" Internal configuration system error");
break;
case ConfigurationUnitResultSource.ConfigurationSet:
Console.WriteLine(" Configuration set is ill-formed");
break;
case ConfigurationUnitResultSource.UnitProcessing:
Console.WriteLine(" DSC resource processing error");
break;
case ConfigurationUnitResultSource.SystemState:
Console.WriteLine(" System state error");
break;
case ConfigurationUnitResultSource.Precondition:
Console.WriteLine(" Dependency failed");
break;
}
}
}
else if (unitResult.State == ConfigurationUnitState.Skipped)
{
Console.WriteLine($"\nUnit skipped: {unit.Type}");
Console.WriteLine($" Reason: {unitResult.ResultInformation.Description}");
}
}
Test Configuration Errors
var testResult = await processor.TestSetAsync(configSet);
foreach (var unitResult in testResult.UnitResults)
{
var unit = unitResult.Unit;
var result = unitResult.ResultInformation;
switch (unitResult.TestResult)
{
case ConfigurationTestResult.Positive:
Console.WriteLine($"{unit.Type}: In desired state");
break;
case ConfigurationTestResult.Negative:
Console.WriteLine($"{unit.Type}: NOT in desired state");
break;
case ConfigurationTestResult.Failed:
Console.WriteLine($"{unit.Type}: Test FAILED");
Console.WriteLine($" Error: {result.Description}");
Console.WriteLine($" HRESULT: 0x{result.ResultCode:X8}");
break;
case ConfigurationTestResult.NotRun:
Console.WriteLine($"{unit.Type}: Test not run");
if (result.ResultCode != 0)
{
Console.WriteLine($" Reason: {result.Description}");
}
break;
}
}
Common HRESULT Codes
| HRESULT | Name | Description |
|---|---|---|
| 0x00000000 | S_OK | Success |
| 0x80070002 | ERROR_FILE_NOT_FOUND | File not found |
| 0x80070005 | E_ACCESSDENIED | Access denied |
| 0x8007007B | ERROR_INVALID_NAME | Invalid syntax or name |
| 0x80070057 | E_INVALIDARG | Invalid argument |
| 0x80070490 | ERROR_NOT_FOUND | Element not found |
| 0x80070643 | ERROR_INSTALL_FAILURE | Installation failed |
| 0x80070BC9 | ERROR_SUCCESS_REBOOT_REQUIRED | Reboot required |
| 0x80072EFD | WININET_E_CANNOT_CONNECT | Cannot connect to server |
| 0x80072EE7 | ERROR_INTERNET_NAME_NOT_RESOLVED | DNS resolution failed |
| 0x80131500 | COR_E_EXCEPTION | General .NET exception |
Best Practices
1. Always Check Status Codes
// Good
var result = await manager.InstallPackageAsync(package, options);
if (result.Status != InstallResultStatus.Ok)
{
HandleInstallError(result);
return;
}
// Bad - assuming success
var result = await manager.InstallPackageAsync(package, options);
// Continue without checking
2. Provide User-Friendly Messages
string GetUserFriendlyMessage(InstallResult result)
{
return result.Status switch
{
InstallResultStatus.Ok => "Installation completed successfully",
InstallResultStatus.DownloadError => "Failed to download installer. Check your internet connection.",
InstallResultStatus.InstallError => $"Installation failed. Error code: {result.InstallerErrorCode:X}",
InstallResultStatus.BlockedByPolicy => "Installation blocked by your organization's policy",
InstallResultStatus.NoApplicableInstallers => "This package is not compatible with your system",
InstallResultStatus.PackageAgreementsNotAccepted => "You must accept the package license agreement",
_ => $"Installation failed with error: {result.Status}"
};
}
3. Log Detailed Errors
void LogError(InstallResult result, string packageId)
{
_logger.LogError(
"Package installation failed. " +
"PackageId={PackageId}, " +
"Status={Status}, " +
"ExtendedError=0x{ExtendedError:X8}, " +
"InstallerError=0x{InstallerError:X}, " +
"CorrelationData={CorrelationData}",
packageId,
result.Status,
result.ExtendedErrorCode,
result.InstallerErrorCode,
result.CorrelationData
);
}
4. Handle Transient Errors
async Task<InstallResult> InstallWithRetryAsync(
CatalogPackage package,
InstallOptions options,
int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
var result = await _manager.InstallPackageAsync(package, options);
if (result.Status == InstallResultStatus.Ok)
{
return result;
}
// Retry on transient errors
if (result.Status == InstallResultStatus.DownloadError)
{
Console.WriteLine($"Download failed. Retry {i + 1}/{maxRetries}...");
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i)));
continue;
}
// Don't retry permanent errors
return result;
}
throw new Exception("Max retries exceeded");
}
5. Handle Diagnostics
processor.MinimumLevel = DiagnosticLevel.Warning;
processor.Diagnostics += (sender, diagnostics) =>
{
var logLevel = diagnostics.Level switch
{
DiagnosticLevel.Verbose => LogLevel.Trace,
DiagnosticLevel.Informational => LogLevel.Information,
DiagnosticLevel.Warning => LogLevel.Warning,
DiagnosticLevel.Error => LogLevel.Error,
DiagnosticLevel.Critical => LogLevel.Critical,
_ => LogLevel.Debug
};
_logger.Log(logLevel, diagnostics.Message);
};
Related Topics
- PackageManager - Package management operations
- ConfigurationProcessor - Configuration operations
- Events & Progress - Progress tracking