Initial Commit
This commit is contained in:
84
PatchProbe.Cli/Collectors/CbsDismCollector.cs
Normal file
84
PatchProbe.Cli/Collectors/CbsDismCollector.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PatchProbe.Shared.Contracts;
|
||||
using PatchProbe.Shared.Models;
|
||||
|
||||
namespace PatchProbe.Cli.Collectors;
|
||||
|
||||
public sealed class CbsDismCollector(ILogger<CbsDismCollector> logger) : ICollector<List<CbsPackage>>
|
||||
{
|
||||
public async Task<List<CbsPackage>> CollectAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
logger.LogInformation("Collecting CBS/DISM package state");
|
||||
|
||||
var packages = new List<CbsPackage>();
|
||||
|
||||
try
|
||||
{
|
||||
var output = await RunDismAsync(cancellationToken);
|
||||
packages = ParseDismOutput(output);
|
||||
logger.LogInformation("Collected {Count} CBS packages", packages.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "CBS/DISM collection failed");
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
private static async Task<string> RunDismAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = "dism.exe",
|
||||
Arguments = "/Online /Get-Packages /Format:Table",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
using var process = Process.Start(psi) ?? throw new InvalidOperationException("Failed to start dism.exe");
|
||||
var output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
|
||||
await process.WaitForExitAsync(cancellationToken);
|
||||
return output;
|
||||
}
|
||||
|
||||
private static List<CbsPackage> ParseDismOutput(string output)
|
||||
{
|
||||
var packages = new List<CbsPackage>();
|
||||
var lines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// Skip header lines; data rows contain "Package Identity" columns separated by spaces/pipes
|
||||
bool inDataSection = false;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var trimmed = line.Trim();
|
||||
|
||||
if (trimmed.StartsWith("Package Identity", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inDataSection = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inDataSection || string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith('-'))
|
||||
continue;
|
||||
|
||||
// DISM table output uses multiple spaces as column separator
|
||||
var parts = System.Text.RegularExpressions.Regex.Split(trimmed, @"\s{2,}");
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
packages.Add(new CbsPackage
|
||||
{
|
||||
PackageIdentity = parts[0].Trim(),
|
||||
State = parts.Length > 1 ? parts[1].Trim() : null,
|
||||
ReleaseType = parts.Length > 2 ? parts[2].Trim() : null,
|
||||
InstallTime = parts.Length > 3 ? parts[3].Trim() : null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user