winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

OperationWithProgressBase.cs (4125B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="OperationWithProgressBase.cs" company="Microsoft Corporation">
      3 //     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
      4 // </copyright>
      5 // -----------------------------------------------------------------------------
      6 
      7 namespace Microsoft.WinGet.Client.Engine.Helpers
      8 {
      9     using System;
     10     using System.Runtime.InteropServices;
     11     using System.Threading.Tasks;
     12     using Microsoft.WinGet.Common.Command;
     13     using Microsoft.WinGet.Resources;
     14     using Windows.Foundation;
     15 
     16     /// <summary>
     17     /// Base class for async operations with progress.
     18     /// </summary>
     19     /// <typeparam name="TOperationResult">The operation result.</typeparam>
     20     /// <typeparam name="TProgressData">Progress data.</typeparam>
     21     internal abstract class OperationWithProgressBase<TOperationResult, TProgressData>
     22     {
     23         private static bool isProgressEnabled;
     24 
     25         static OperationWithProgressBase()
     26         {
     27             // Progress on arm64 will produce an AV because there's an OS bug where marshaling structs over a certain size fail.
     28             // Fix is in 10.0.26068.0, for build before that disable progress.
     29             if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
     30             {
     31                 var minWindowsVersion = new Version(10, 0, 26068, 0);
     32                 var osVersion = Environment.OSVersion.Version;
     33                 isProgressEnabled = osVersion.CompareTo(minWindowsVersion) >= 0;
     34             }
     35             else
     36             {
     37                 isProgressEnabled = true;
     38             }
     39         }
     40 
     41         /// <summary>
     42         /// Initializes a new instance of the <see cref="OperationWithProgressBase{TOperationResult, TProgressData}"/> class.
     43         /// </summary>
     44         /// <param name="pwshCmdlet">A <see cref="PowerShellCmdlet" /> instance.</param>
     45         /// <param name="activity">Activity.</param>
     46         public OperationWithProgressBase(
     47             PowerShellCmdlet pwshCmdlet,
     48             string activity)
     49         {
     50             this.PwshCmdlet = pwshCmdlet;
     51             this.ActivityId = pwshCmdlet.GetNewProgressActivityId();
     52             this.Activity = activity;
     53         }
     54 
     55         /// <summary>
     56         /// Gets the PowerShellCmdlet.
     57         /// </summary>
     58         protected PowerShellCmdlet PwshCmdlet { get; }
     59 
     60         /// <summary>
     61         /// Gets the progress activity id.
     62         /// </summary>
     63         protected int ActivityId { get; }
     64 
     65         /// <summary>
     66         /// Gets the activity.
     67         /// </summary>
     68         protected string Activity { get; }
     69 
     70         /// <summary>
     71         /// Progress callback.
     72         /// </summary>
     73         /// <param name="operation">Async operation in progress.</param>
     74         /// <param name="progress">Progress data.</param>
     75         public abstract void Progress(IAsyncOperationWithProgress<TOperationResult, TProgressData> operation, TProgressData progress);
     76 
     77         /// <summary>
     78         /// Starts the operation and executes it as task.
     79         /// Supports cancellation.
     80         /// </summary>
     81         /// <param name="func">Lambda with operation.</param>
     82         /// <returns>TOperationReturn.</returns>
     83         public async Task<TOperationResult> ExecuteAsync(Func<IAsyncOperationWithProgress<TOperationResult, TProgressData>> func)
     84         {
     85             var operation = func();
     86 
     87             if (isProgressEnabled)
     88             {
     89                 operation.Progress = this.Progress;
     90             }
     91 
     92             try
     93             {
     94                 return await operation.AsTask(this.PwshCmdlet.GetCancellationToken());
     95             }
     96             finally
     97             {
     98                 this.Complete();
     99             }
    100         }
    101 
    102         /// <summary>
    103         /// Completes progress for this activity.
    104         /// </summary>
    105         protected virtual void Complete()
    106         {
    107             this.PwshCmdlet.CompleteProgress(this.ActivityId, this.Activity, Resources.Completed, true);
    108         }
    109     }
    110 }