/Source/Deployer.NetFx/DismImageService.cs

https://github.com/WOA-Project/WOA-Deployer · C# · 117 lines · 97 code · 19 blank · 1 comment · 9 complexity · 51bc191c8a8b7ba8ef21ce16db0518e3 MD5 · raw file

  1. using System;
  2. using System.Globalization;
  3. using System.Reactive.Linq;
  4. using System.Reactive.Subjects;
  5. using System.Text.RegularExpressions;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Deployer.Core;
  9. using Deployer.Core.Exceptions;
  10. using Deployer.Core.FileSystem;
  11. using Deployer.Core.Services;
  12. using Deployer.Core.Utils;
  13. using Serilog;
  14. using Zafiro.Core;
  15. using Zafiro.Core.FileSystem;
  16. namespace Deployer.NetFx
  17. {
  18. public class DismImageService : ImageServiceBase
  19. {
  20. private readonly Regex percentRegex = new Regex(@"(\d*.\d*)%");
  21. public DismImageService(IFileSystemOperations fileSystemOperations) : base(fileSystemOperations)
  22. {
  23. }
  24. public override Task ApplyImage(IPartition target, string imagePath, int imageIndex = 1,
  25. bool useCompact = false,
  26. IOperationProgress progressObserver = null, CancellationToken token = default(CancellationToken))
  27. {
  28. return ApplyImage(target.Root, imagePath, imageIndex, useCompact, progressObserver, token);
  29. }
  30. public override Task ApplyImage(string targetDriveRoot, string imagePath, int imageIndex = 1,
  31. bool useCompact = false,
  32. IOperationProgress progressObserver = null, CancellationToken token = default(CancellationToken))
  33. {
  34. EnsureValidParameters(targetDriveRoot, imagePath, imageIndex);
  35. var compact = useCompact ? "/compact" : "";
  36. var args =
  37. $@"/Apply-Image {compact} /ImageFile:""{imagePath}"" /Index:{imageIndex} /ApplyDir:{targetDriveRoot}";
  38. return Run(args, progressObserver, token);
  39. }
  40. //dism.exe /Capture-Image /ImageFile:D:\Image_of_Windows_10.wim /CaptureDir:C:\ /Name:Windows_10 /compress:fast
  41. public override Task CaptureImage(IPartition source, string destination,
  42. IOperationProgress progressObserver = null,
  43. CancellationToken cancellationToken = default(CancellationToken))
  44. {
  45. var capturePath = source?.Root;
  46. if (capturePath == null)
  47. {
  48. throw new ApplicationException("The capture path cannot be null");
  49. }
  50. var args = $@"/Capture-Image /ImageFile:""{destination}"" /CaptureDir:{capturePath} /Name:WOA /compress:fast";
  51. return Run(args, progressObserver, cancellationToken);
  52. }
  53. private async Task Run(string args, IOperationProgress progressObserver, CancellationToken token)
  54. {
  55. var dismName = WindowsCommandLineUtils.Dism;
  56. ISubject<string> outputSubject = new Subject<string>();
  57. IDisposable stdOutputSubscription = null;
  58. if (progressObserver != null)
  59. {
  60. stdOutputSubscription = outputSubject
  61. .Select(GetPercentage)
  62. .Where(d => !double.IsNaN(d))
  63. .Subscribe(progressObserver.Percentage);
  64. }
  65. Log.Verbose("We are about to run DISM: {ExecName} {Parameters}", dismName, args);
  66. var processResults = await ProcessMixin.RunProcess(dismName, args, outputSubject, cancellationToken: token);
  67. progressObserver?.Percentage.OnNext(double.NaN);
  68. if (processResults.ExitCode != 0)
  69. {
  70. Log.Error("There has been a problem during deployment: DISM failed {Results}", processResults);
  71. throw new DeploymentException($"There has been a problem during deployment: DISM exited with code {processResults.ExitCode}");
  72. }
  73. stdOutputSubscription?.Dispose();
  74. }
  75. private double GetPercentage(string dismOutput)
  76. {
  77. if (dismOutput == null)
  78. {
  79. return double.NaN;
  80. }
  81. var matches = percentRegex.Match(dismOutput);
  82. if (matches.Success)
  83. {
  84. var value = matches.Groups[1].Value;
  85. try
  86. {
  87. var percentage = double.Parse(value, CultureInfo.InvariantCulture) / 100D;
  88. return percentage;
  89. }
  90. catch (FormatException)
  91. {
  92. Log.Warning($"Cannot convert {value} to double");
  93. }
  94. }
  95. return double.NaN;
  96. }
  97. }
  98. }