diff --git a/src/c#/GeneralUpdate.Drivelution/Abstractions/IGeneralDrivelution.cs b/src/c#/GeneralUpdate.Drivelution/Abstractions/IGeneralDrivelution.cs
index f3d95162..ddf41291 100644
--- a/src/c#/GeneralUpdate.Drivelution/Abstractions/IGeneralDrivelution.cs
+++ b/src/c#/GeneralUpdate.Drivelution/Abstractions/IGeneralDrivelution.cs
@@ -12,9 +12,14 @@ public interface IGeneralDrivelution
///
/// Driver information
/// Update strategy
+ /// Optional progress reporter for real-time status updates.
/// Cancellation token
/// Update result
- Task UpdateAsync(DriverInfo driverInfo, UpdateStrategy strategy, CancellationToken cancellationToken = default);
+ Task UpdateAsync(
+ DriverInfo driverInfo,
+ UpdateStrategy strategy,
+ IProgress? progress = null,
+ CancellationToken cancellationToken = default);
///
/// Validates driver asynchronously
diff --git a/src/c#/GeneralUpdate.Drivelution/Abstractions/Models/UpdateProgress.cs b/src/c#/GeneralUpdate.Drivelution/Abstractions/Models/UpdateProgress.cs
new file mode 100644
index 00000000..150c33ae
--- /dev/null
+++ b/src/c#/GeneralUpdate.Drivelution/Abstractions/Models/UpdateProgress.cs
@@ -0,0 +1,44 @@
+using GeneralUpdate.Drivelution.Abstractions.Models;
+
+namespace GeneralUpdate.Drivelution.Abstractions.Models;
+
+///
+/// Progress information reported during a driver update operation.
+/// Suitable for binding to UI progress bars and status displays.
+///
+public class UpdateProgress
+{
+ ///
+ /// Current update status in the pipeline.
+ ///
+ public UpdateStatus CurrentStatus { get; init; }
+
+ ///
+ /// Name of the currently executing pipeline step.
+ ///
+ public string StepName { get; init; } = string.Empty;
+
+ ///
+ /// Overall completion percentage (0-100).
+ ///
+ public int Percentage { get; init; }
+
+ ///
+ /// Human-readable progress message.
+ ///
+ public string Message { get; init; } = string.Empty;
+
+ ///
+ /// Index of the current step (0-based).
+ ///
+ public int StepIndex { get; init; }
+
+ ///
+ /// Total number of steps in the pipeline.
+ ///
+ public int TotalSteps { get; init; }
+
+ ///
+ public override string ToString()
+ => $"[{Percentage}%] {StepName} ({StepIndex + 1}/{TotalSteps}): {Message}";
+}
diff --git a/src/c#/GeneralUpdate.Drivelution/Core/Pipeline/BaseDriverUpdater.cs b/src/c#/GeneralUpdate.Drivelution/Core/Pipeline/BaseDriverUpdater.cs
index 029ab0fd..8fc6d335 100644
--- a/src/c#/GeneralUpdate.Drivelution/Core/Pipeline/BaseDriverUpdater.cs
+++ b/src/c#/GeneralUpdate.Drivelution/Core/Pipeline/BaseDriverUpdater.cs
@@ -49,6 +49,7 @@ protected BaseDriverUpdater(
public async Task UpdateAsync(
DriverInfo driverInfo,
UpdateStrategy strategy,
+ IProgress? progress = null,
CancellationToken cancellationToken = default)
{
var result = new UpdateResult
@@ -70,6 +71,7 @@ public async Task UpdateAsync(
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
cancellationToken, timeoutCts.Token);
+ int stepCount = 0;
try
{
GeneralTracer.Info($"Starting driver update: {driverInfo.Name} v{driverInfo.Version} " +
@@ -78,8 +80,9 @@ public async Task UpdateAsync(
var steps = GetPipelineSteps(strategy)
.Where(s => s.ShouldExecute(context))
.ToList();
+ stepCount = steps.Count;
- var totalSteps = steps.Count;
+ var totalSteps = stepCount;
int stepIndex = 0;
PipelineResult? lastStepResult = null;
@@ -87,7 +90,16 @@ public async Task UpdateAsync(
{
stepIndex++;
OnStepStarted?.Invoke(step.StepName);
- ReportProgress((int)((float)(stepIndex - 1) / totalSteps * 100), $"Running: {step.StepName}");
+
+ progress?.Report(new UpdateProgress
+ {
+ CurrentStatus = UpdateStatus.Updating,
+ StepName = step.StepName,
+ Percentage = (int)((float)(stepIndex - 1) / totalSteps * 100),
+ Message = $"Running: {step.StepName}",
+ StepIndex = stepIndex - 1,
+ TotalSteps = totalSteps
+ });
// Execute step with retry on transient failures
try
@@ -179,7 +191,17 @@ public async Task UpdateAsync(
{
result.EndTime = DateTime.UtcNow;
GeneralTracer.Info($"Driver update finished. Duration={result.DurationMs}ms, Success={result.Success}");
- ReportProgress(100, result.Success ? "Completed" : "Failed");
+
+ progress?.Report(new UpdateProgress
+ {
+ CurrentStatus = result.Status,
+ StepName = result.Success ? "Completed" : "Failed",
+ Percentage = 100,
+ Message = result.Success ? "Driver update completed successfully" : result.Error?.Message ?? "Failed",
+ StepIndex = stepCount,
+ TotalSteps = stepCount
+ });
+
OnUpdateCompleted?.Invoke(result);
}
diff --git a/src/c#/GeneralUpdate.Drivelution/GeneralDrivelution.cs b/src/c#/GeneralUpdate.Drivelution/GeneralDrivelution.cs
index b7238055..c5d39410 100644
--- a/src/c#/GeneralUpdate.Drivelution/GeneralDrivelution.cs
+++ b/src/c#/GeneralUpdate.Drivelution/GeneralDrivelution.cs
@@ -60,6 +60,7 @@ public static IGeneralDrivelution Create(IServiceProvider serviceProvider)
/// Update result
public static async Task QuickUpdateAsync(
DriverInfo driverInfo,
+ IProgress? progress = null,
CancellationToken cancellationToken = default)
{
GeneralTracer.Info($"GeneralDrivelution.QuickUpdateAsync: starting quick driver update. Driver={driverInfo.Name}, Version={driverInfo.Version}");
@@ -71,7 +72,7 @@ public static async Task QuickUpdateAsync(
RetryIntervalSeconds = 5
};
- var result = await updater.UpdateAsync(driverInfo, strategy, cancellationToken);
+ var result = await updater.UpdateAsync(driverInfo, strategy, progress, cancellationToken);
GeneralTracer.Info($"GeneralDrivelution.QuickUpdateAsync: quick driver update completed. Success={result.Success}, Status={result.Status}, DurationMs={result.DurationMs}");
return result;
}
@@ -86,11 +87,12 @@ public static async Task QuickUpdateAsync(
public static async Task QuickUpdateAsync(
DriverInfo driverInfo,
UpdateStrategy strategy,
+ IProgress? progress = null,
CancellationToken cancellationToken = default)
{
GeneralTracer.Info($"GeneralDrivelution.QuickUpdateAsync(strategy): starting driver update with custom strategy. Driver={driverInfo.Name}, Version={driverInfo.Version}, RequireBackup={strategy.RequireBackup}, RetryCount={strategy.RetryCount}");
var updater = Create();
- var result = await updater.UpdateAsync(driverInfo, strategy, cancellationToken);
+ var result = await updater.UpdateAsync(driverInfo, strategy, progress, cancellationToken);
GeneralTracer.Info($"GeneralDrivelution.QuickUpdateAsync(strategy): driver update completed. Success={result.Success}, Status={result.Status}, DurationMs={result.DurationMs}");
return result;
}
diff --git a/src/c#/GeneralUpdate.Drivelution/MacOS/Implementation/MacOsGeneralDrivelution.cs b/src/c#/GeneralUpdate.Drivelution/MacOS/Implementation/MacOsGeneralDrivelution.cs
index d23a345d..7b2a22f2 100644
--- a/src/c#/GeneralUpdate.Drivelution/MacOS/Implementation/MacOsGeneralDrivelution.cs
+++ b/src/c#/GeneralUpdate.Drivelution/MacOS/Implementation/MacOsGeneralDrivelution.cs
@@ -26,6 +26,7 @@ public class MacOsGeneralDrivelution : IGeneralDrivelution
public Task UpdateAsync(
DriverInfo driverInfo,
UpdateStrategy strategy,
+ IProgress? progress = null,
CancellationToken cancellationToken = default)
{
throw new PlatformNotSupportedException(