public void TestMessages() { var progress = new TestProgress(); using (var wrapped = new WrappedProgress(progress)) { var progressA = wrapped.GetChildProgress(); var progressB = wrapped.GetChildProgress(); progressA.Report(new ProgressData(10, "A1")); Assert.AreEqual("A1", progress.Last.Message); progressA.Report(new ProgressData(20, "A2")); Assert.AreEqual("A2", progress.Last.Message); progressB.Report(new ProgressData(10, "B1")); Assert.AreEqual("B1", progress.Last.Message); progressA.Report(new ProgressData(100, "A3")); Assert.AreEqual("A3", progress.Last.Message); progressB.Report(new ProgressData(100, "B2")); Assert.AreEqual("B2", progress.Last.Message); } }
public void TestZeroWeight() { var progress = new TestProgress(); using (var wrapped = new WrappedProgress(progress)) { Assert.Throws <ArgumentOutOfRangeException>(() => wrapped.GetChildProgress(0), "Zero weight must throw ArgumentOutOfRange exception."); Assert.Throws <ArgumentOutOfRangeException>(() => wrapped.GetChildProgress(-1), "Negative weight must throw ArgumentOutOfRange exception."); } }
public void TestNullParent() { using (var wrapped = new WrappedProgress(null)) { var p1 = wrapped.GetChildProgress(); var p2 = wrapped.GetChildProgress(); // The following may not throw. This class should by design handle cases where parent is null, // by simply swallowing sub-progress reports. p1.Report(new ProgressData(10, "test")); p2.Report(new ProgressData(10, "test")); } }
protected override async Task <bool> Save(CancellationToken cancellationToken, IProgress <ProgressData> progress) { AppxPackerOptions opts = 0; if (!this.Validate.CurrentValue) { opts |= AppxPackerOptions.NoValidation; } if (!this.Compress.CurrentValue) { opts |= AppxPackerOptions.NoCompress; } using (var progressWrapper = new WrappedProgress(progress)) { var progress1 = progressWrapper.GetChildProgress(50); var progress2 = this.Sign.CurrentValue ? progressWrapper.GetChildProgress(30) : null; await this.appxPacker.Pack(this.InputPath.CurrentValue, this.OutputPath.CurrentValue, opts, cancellationToken, progress1).ConfigureAwait(false); if (this.Sign.CurrentValue) { var manager = await this.signingManagerFactory.GetProxyFor(SelfElevationLevel.HighestAvailable, cancellationToken).ConfigureAwait(false); switch (this.SelectedCertificate.Store.CurrentValue) { case CertificateSource.Personal: await manager.SignPackageWithInstalled(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.SelectedPersonalCertificate.CurrentValue?.Model, this.SelectedCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; case CertificateSource.Pfx: await manager.SignPackageWithPfx(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.PfxPath.CurrentValue, this.SelectedCertificate.Password.CurrentValue, this.SelectedCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; case CertificateSource.DeviceGuard: await manager.SignPackageWithDeviceGuardFromUi(this.OutputPath.CurrentValue, this.SelectedCertificate.DeviceGuard.CurrentValue, this.SelectedCertificate.TimeStamp.CurrentValue, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; } } } return(true); }
public void TestWrongChildrenReports() { var progress = new TestProgress(); using (var wrapped = new WrappedProgress(progress)) { var p1 = wrapped.GetChildProgress(); var p2 = wrapped.GetChildProgress(); p1.Report(new ProgressData(200, null)); Assert.AreEqual(50, progress.Last.Progress, "Even though the children may report over 100% completion, the overall progress may not overflow."); p2.Report(new ProgressData(300, null)); Assert.AreEqual(100, progress.Last.Progress, "Even though the children may report over 100% completion, the overall progress may not overflow."); } }
public async Task Dismount(string name, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = default) { using var wrappedProgress = new WrappedProgress(progress); var p1 = wrappedProgress.GetChildProgress(); var p2 = wrappedProgress.GetChildProgress(); var allVolumes = await this.GetAll(cancellationToken, p1).ConfigureAwait(false); var volume = allVolumes.FirstOrDefault(v => string.Equals(name, v.Name, StringComparison.OrdinalIgnoreCase)); if (volume == null) { return; } await this.Dismount(volume, cancellationToken, p2).ConfigureAwait(false); }
public void TestWrappedProgress() { var progress = new TestProgress(); using (var wrapped = new WrappedProgress(progress)) { Assert.AreEqual(0, progress.Last.Progress); const int weight1 = 700; const int weight2 = 200; const int weight3 = 100; var p1 = wrapped.GetChildProgress(weight1); var p2 = wrapped.GetChildProgress(weight2); var p3 = wrapped.GetChildProgress(weight3); p1.Report(new ProgressData(0, null)); p2.Report(new ProgressData(0, null)); p3.Report(new ProgressData(0, null)); Assert.AreEqual(0, progress.Last.Progress, "If all sub elements report 0% progress, then the overall progress is also 0%."); p1.Report(new ProgressData(100, null)); // (100% * 700 + 0% * 200 + 0% * 100) / (100 + 200 + 700) = 70% Assert.AreEqual(70, progress.Last.Progress); p2.Report(new ProgressData(50, null)); // (100% * 700 + 50% * 200 + 0% * 100) / (100 + 200 + 700) = 80% Assert.AreEqual(80, progress.Last.Progress); p3.Report(new ProgressData(10, null)); // (100% * 700 + 50% * 200 + 10% * 100) / (100 + 200 + 700) = 81% Assert.AreEqual(81, progress.Last.Progress); p2.Report(new ProgressData(100, null)); // (100% * 700 + 100% * 200 + 10% * 100) / (100 + 200 + 700) = 91% Assert.AreEqual(91, progress.Last.Progress); p3.Report(new ProgressData(100, null)); // (100% * 700 + 100% * 200 + 100% * 100) / (100 + 200 + 700) = 100% Assert.AreEqual(100, progress.Last.Progress); p3.Report(new ProgressData(0, null)); // (100% * 700 + 100% * 200 + 0% * 100) / (100 + 200 + 700) = 90% Assert.AreEqual(90, progress.Last.Progress, "If progress of a child element goes backward, the reported wrapped progress should also reflect this."); } }
protected override async Task <bool> Save(CancellationToken cancellationToken, IProgress <ProgressData> progress) { var manager = await this.signingManagerFactory.GetProxyFor(SelfElevationLevel.AsInvoker, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); using (var progressAll = new WrappedProgress(progress)) { // ReSharper disable once AccessToDisposedClosure var progressForFiles = this.Files.ToDictionary(p => p, _ => progressAll.GetChildProgress()); foreach (var file in this.Files) { var currentProgress = progressForFiles[file]; cancellationToken.ThrowIfCancellationRequested(); string timeStampUrl; switch (this.CertificateSelector.TimeStampSelectionMode.CurrentValue) { case TimeStampSelectionMode.None: timeStampUrl = null; break; case TimeStampSelectionMode.Auto: timeStampUrl = "auto"; break; case TimeStampSelectionMode.Url: timeStampUrl = this.CertificateSelector.TimeStamp.CurrentValue; break; default: throw new ArgumentOutOfRangeException(); } switch (this.CertificateSelector.Store.CurrentValue) { case CertificateSource.Pfx: await manager.SignPackageWithPfx(file, this.OverrideSubject.CurrentValue, this.CertificateSelector.PfxPath.CurrentValue, this.CertificateSelector.Password.CurrentValue, timeStampUrl, this.IncreaseVersion.CurrentValue, cancellationToken, currentProgress).ConfigureAwait(false); break; case CertificateSource.Personal: await manager.SignPackageWithInstalled(file, this.OverrideSubject.CurrentValue, this.CertificateSelector.SelectedPersonalCertificate.CurrentValue.Model, timeStampUrl, this.IncreaseVersion.CurrentValue, cancellationToken, currentProgress).ConfigureAwait(false); break; case CertificateSource.DeviceGuard: await manager.SignPackageWithDeviceGuardFromUi(file, this.CertificateSelector.DeviceGuard.CurrentValue, timeStampUrl, this.IncreaseVersion.CurrentValue, cancellationToken, currentProgress).ConfigureAwait(false); break; } } } return(true); }
public void TestInvalidOperations() { var progress = new TestProgress(); using (var wrapped = new WrappedProgress(progress)) { var p1 = wrapped.GetChildProgress(); p1.Report(new ProgressData(50, "test")); Assert.Throws <InvalidOperationException>(() => wrapped.GetChildProgress(), "Creating a new child progress should be disallowed once at lest one sub-progress has already reported."); } var progress2 = new TestProgress(); using (var wrapped = new WrappedProgress(progress2, false)) { var p1 = wrapped.GetChildProgress(); p1.Report(new ProgressData(50, "test")); // This may not throw because of the second argument in WrappedProgress ctor wrapped.GetChildProgress(); } }
public async Task SetDefault(string drivePath, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = default) { using var wrappedProgress = new WrappedProgress(progress); var p1 = wrappedProgress.GetChildProgress(); var p2 = wrappedProgress.GetChildProgress(); var allVolumes = await this.GetAll(cancellationToken, p1).ConfigureAwait(false); drivePath = GetDriveLetterFromPath(drivePath); Logger.Info("Looking for volume {0}...", drivePath); foreach (var item in allVolumes) { Logger.Debug(" * Found volume '{0}'", item.PackageStorePath); } var volume = allVolumes.FirstOrDefault(v => GetDriveLetterFromPath(v.PackageStorePath) == drivePath); if (volume == null) { throw new DriveNotFoundException($"Could not find volume '{drivePath}'"); } await this.SetDefault(volume, cancellationToken, p2).ConfigureAwait(false); }
public async Task <List <Log> > GetLogs(int maxCount, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = default) { Logger.Info("Getting last {0} log files...", maxCount); var allLogs = new List <Log>(); using var ps = await PowerShellSession.CreateForModule().ConfigureAwait(false); using var script = ps.AddScript("(Get-WinEvent -ListLog *Microsoft-Windows-*Appx* -ErrorAction SilentlyContinue).ProviderNames"); using var logs = await ps.InvokeAsync().ConfigureAwait(false); var logNames = logs.ToArray(); var progresses = new IProgress <ProgressData> [logNames.Length]; using (var wrapperProgress = new WrappedProgress(progress ?? new Progress <ProgressData>())) { for (var index = 0; index < logNames.Length; index++) { cancellationToken.ThrowIfCancellationRequested(); progresses[index] = wrapperProgress.GetChildProgress(); } var allTasks = new List <Task <IList <Log> > >(); for (var index = 0; index < logNames.Length; index++) { cancellationToken.ThrowIfCancellationRequested(); var item = logNames[index]; var itemProgress = progresses[index]; allTasks.Add(this.GetLogsFromProvider(item, maxCount, cancellationToken, itemProgress)); } await Task.WhenAll(allTasks).ConfigureAwait(false); foreach (var item in allTasks) { allLogs.AddRange(await item.ConfigureAwait(false)); } } if (maxCount > 0) { return(allLogs.OrderByDescending(l => l.DateTime).Take(maxCount).ToList()); } return(allLogs); }
public async Task CreateVolume( string packagePath, string volumePath, long?customSize, CancellationToken cancellationToken = default, IProgress <ProgressData> progressReporter = null) { if (packagePath == null) { throw new ArgumentNullException(nameof(packagePath), "Package path must not be empty."); } if (volumePath == null) { throw new ArgumentNullException(nameof(volumePath), "Volume path must not be empty."); } var packageFileInfo = new FileInfo(packagePath); if (!packageFileInfo.Exists) { throw new FileNotFoundException($"File {packagePath} does not exist.", packagePath); } switch (Path.GetExtension(volumePath).ToLowerInvariant()) { case FileConstants.AppAttachVhdExtension: case FileConstants.AppAttachVhdxExtension: break; default: throw new NotSupportedException($"Disk format {Path.GetExtension(volumePath)} is not supported."); } var volumeFileInfo = new FileInfo(volumePath); if (volumeFileInfo.Directory != null && !volumeFileInfo.Directory.Exists) { volumeFileInfo.Directory.Create(); } var tmpPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + Path.GetExtension(volumePath)); using var progress = new WrappedProgress(progressReporter); // ReSharper disable once UnusedVariable var progressSize = customSize <= 0 ? progress.GetChildProgress(30) : null; var progressInitializeDisk = progress.GetChildProgress(100); var progressExpand = progress.GetChildProgress(120); try { long minimumSize; if (customSize.HasValue && customSize.Value > 0) { minimumSize = 1024 * 1024 * customSize.Value; } else { ISizeCalculator sizeCalculator = new VhdSizeCalculator(); minimumSize = await sizeCalculator.GetRequiredSize(packagePath, cancellationToken : cancellationToken).ConfigureAwait(false); } var wrapper = new DiskPartWrapper(); try { Logger.Debug("Getting drives (NTFS, ready) and volumes..."); var allDrives = DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveFormat == "NTFS").Select(d => d.Name.ToLowerInvariant()).ToArray(); foreach (var item in allDrives) { Logger.Debug("* Drive: " + item); } var allVolumes = await MountVolumeHelper.GetVolumeIdentifiers().ConfigureAwait(false); foreach (var item in allDrives) { Logger.Debug("* Volume: " + item); } await wrapper.CreateVhdAndAssignDriveLetter(tmpPath, minimumSize, cancellationToken, progressInitializeDisk).ConfigureAwait(false); var newVolumes = (await MountVolumeHelper.GetVolumeIdentifiers().ConfigureAwait(false)).Except(allVolumes).ToArray(); foreach (var item in newVolumes) { Logger.Debug("* New volume: " + item); } var newDrives = DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveFormat == "NTFS").Select(d => d.Name.ToLowerInvariant()).Except(allDrives).ToArray(); foreach (var item in newDrives) { Logger.Debug("* New drive: " + item); } if (newDrives.Length != 1 || newVolumes.Length != 1) { throw new InvalidOperationException("Could not mount the drive."); } cancellationToken.ThrowIfCancellationRequested(); await this.ExpandMsix(packagePath, newDrives.First() + Path.GetFileNameWithoutExtension(packagePath), cancellationToken, progressExpand).ConfigureAwait(false); } finally { await wrapper.DismountVhd(tmpPath, cancellationToken).ConfigureAwait(false); } if (File.Exists(tmpPath)) { File.Move(tmpPath, volumeFileInfo.FullName, true); } } finally { if (File.Exists(tmpPath)) { File.Delete(tmpPath); } } }
private async void OnRemovePackage() { if (!this.IsAnySelected()) { return; } var config = await this.configurationService.GetCurrentConfigurationAsync().ConfigureAwait(false); if (config.UiConfiguration.ConfirmDeletion) { var options = new List <string> { "Remove for current user", "Do not remove" }; var singleSelection = this.GetSingleOrDefaultSelection(); if (singleSelection != null) { var caption = "Are you sure you want to remove " + singleSelection.DisplayName + " " + singleSelection.Version + "? This operation is irreversible."; var selectedOption = this.interactionService.ShowMessage(caption, options, "Removing package", systemButtons: InteractionResult.Cancel); if (selectedOption != 0) { return; } } else { var selection = this.application.ApplicationState.Packages.SelectedPackages; var caption = "Are you sure you want to remove " + selection.Count + " packages? This operation is irreversible."; var selectedOption = this.interactionService.ShowMessage(caption, options, "Removing package", systemButtons: InteractionResult.Cancel); if (selectedOption != 0) { return; } } } var context = this.busyManager.Begin(); try { using var wrappedProgress = new WrappedProgress(context); var p1 = wrappedProgress.GetChildProgress(70); var p2 = wrappedProgress.GetChildProgress(30); var manager = await this.packageInstallerProvider.GetProxyFor(SelfElevationLevel.AsInvoker).ConfigureAwait(false); var removedPackageNames = this.application.ApplicationState.Packages.SelectedPackages.Select(p => p.DisplayName).ToArray(); var removedPackages = this.application.ApplicationState.Packages.SelectedPackages.Select(p => p.PackageId).ToArray(); await manager.Remove(removedPackages, progress : p1).ConfigureAwait(false); await this.application.CommandExecutor.Invoke(this, new SelectPackagesCommand()).ConfigureAwait(false); switch (removedPackages.Length) { case 1: #pragma warning disable 4014 this.interactionService.ShowToast("App removed", $"{removedPackageNames.FirstOrDefault()} has been just removed.", InteractionType.None); #pragma warning restore 4014 break; default: #pragma warning disable 4014 this.interactionService.ShowToast("Apps removed", $"{removedPackages.Length} apps has been just removed.", InteractionType.None); #pragma warning restore 4014 break; } await this.application.CommandExecutor.Invoke <GetPackagesCommand, IList <InstalledPackage> >(this, new GetPackagesCommand(), progress : p2).ConfigureAwait(false); } catch (Exception exception) { this.interactionService.ShowError("Could not remove the package.", exception); } finally { this.busyManager.End(context); } }
private async void OnAddPackage(string packagePath, bool forAllUsers) { if (packagePath == null) { if (forAllUsers) { if (!this.interactionService.SelectFile(FileDialogSettings.FromFilterString(new DialogFilterBuilder("*" + FileConstants.MsixExtension, "*" + FileConstants.AppxExtension).BuildFilter()), out packagePath)) { return; } } else { if (!this.interactionService.SelectFile( // ReSharper disable StringLiteralTypo FileDialogSettings.FromFilterString(new DialogFilterBuilder("*" + FileConstants.MsixExtension, "*" + FileConstants.AppxExtension, "*" + FileConstants.AppxBundleExtension, "*" + FileConstants.AppInstallerExtension, FileConstants.AppxManifestFile).BuildFilter()), out packagePath)) // ReSharper restore StringLiteralTypo { return; } } } AddAppxPackageOptions options = 0; if (forAllUsers) { options |= AddAppxPackageOptions.AllUsers; } options |= AddAppxPackageOptions.KillRunningApps; var context = this.busyManager.Begin(); try { using var wrappedProgress = new WrappedProgress(context); var p1 = wrappedProgress.GetChildProgress(90); var p2 = wrappedProgress.GetChildProgress(10); var manager = await this.packageInstallerProvider.GetProxyFor(forAllUsers?SelfElevationLevel.AsAdministrator : SelfElevationLevel.AsInvoker).ConfigureAwait(false); await manager.Add(packagePath, options, progress : p1).ConfigureAwait(false); AppxIdentity appxIdentity = null; if (!string.Equals(FileConstants.AppInstallerExtension, Path.GetExtension(packagePath), StringComparison.OrdinalIgnoreCase)) { appxIdentity = await new AppxIdentityReader().GetIdentity(packagePath).ConfigureAwait(false); #pragma warning disable 4014 this.interactionService.ShowToast("App installed", $"{appxIdentity.Name} has been just installed.", InteractionType.None); #pragma warning restore 4014 } else { #pragma warning disable 4014 this.interactionService.ShowToast("App installed", $"A new app has been just installed from {Path.GetFileName(packagePath)}.", InteractionType.None); #pragma warning restore 4014 } var allPackages = await this.application.CommandExecutor.Invoke <GetPackagesCommand, IList <InstalledPackage> >(this, new GetPackagesCommand(forAllUsers ? PackageFindMode.AllUsers : PackageFindMode.CurrentUser), progress : p2).ConfigureAwait(false); if (appxIdentity != null) { var selected = allPackages.FirstOrDefault(p => p.Name == appxIdentity.Name); if (selected != null) { //this.application.ApplicationState.Packages.SelectedPackages.Clear(); //this.application.ApplicationState.Packages.SelectedPackages.Add(selected); await this.application.CommandExecutor.Invoke(this, new SelectPackagesCommand(selected.ManifestLocation)).ConfigureAwait(false); } } else { await this.application.CommandExecutor.Invoke(this, new SelectPackagesCommand()).ConfigureAwait(false); } } catch (Exception exception) { Logger.Error(exception); this.interactionService.ShowError(exception.Message, exception); } finally { this.busyManager.End(context); } }
protected override async Task <bool> Save(CancellationToken cancellationToken, IProgress <ProgressData> progress) { var temporaryFiles = new List <string>(); try { var fileListBuilder = new PackageFileListBuilder(); fileListBuilder.AddDirectory(this.InputPath.CurrentValue, true, null); if (this.PrePackOptions != null && !this.PrePackOptions.ManifestPresent) { if (!this.PrePackOptions.CanConvert) { throw new InvalidOperationException("The selected folder does not contain a manifest file and any executable files. It cannot be packed to MSIX format."); } if (!string.IsNullOrEmpty(this.InputPath.CurrentValue)) { progress.Report(new ProgressData(0, "Creating manifest file...")); var options = new AppxManifestCreatorOptions { CreateLogo = this.PrePackOptions.CreateLogo, EntryPoints = this.PrePackOptions.EntryPoints.Where(e => e.IsChecked).Select(e => e.Value).ToArray(), PackageDisplayName = Path.GetFileName(this.InputPath.CurrentValue), RegistryFile = this.PrePackOptions.SelectedRegistry?.FilePath == null ? null : new FileInfo(this.PrePackOptions.SelectedRegistry.FilePath) }; // ReSharper disable once AssignNullToNotNullAttribute await foreach (var result in this.manifestCreator.CreateManifestForDirectory(new DirectoryInfo(this.InputPath.CurrentValue), options, cancellationToken).ConfigureAwait(false)) { temporaryFiles.Add(result.SourcePath); if (result.PackageRelativePath == null) { continue; } fileListBuilder.AddFile(result.SourcePath, result.PackageRelativePath); } } } using var progressWrapper = new WrappedProgress(progress); var progress1 = progressWrapper.GetChildProgress(50); var progress2 = this.Sign.CurrentValue ? progressWrapper.GetChildProgress(30) : null; var tempFileList = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".list"); temporaryFiles.Add(tempFileList); var tempManifestPath = Path.Combine(Path.GetTempPath(), "AppxManifest-" + Guid.NewGuid().ToString("N") + ".xml"); temporaryFiles.Add(tempManifestPath); var srcManifest = fileListBuilder.GetManifestSourcePath(); if (srcManifest == null || !File.Exists(srcManifest)) { throw new InvalidOperationException("The selected folder cannot be packed because it has no manifest, and MSIX Hero was unable to create one. A manifest can be only created if the selected folder contains any executable file."); } // Copy manifest to a temporary file var injector = new MsixHeroBrandingInjector(); await using (var manifestStream = File.OpenRead(fileListBuilder.GetManifestSourcePath())) { var xml = await XDocument.LoadAsync(manifestStream, LoadOptions.None, cancellationToken).ConfigureAwait(false); await injector.Inject(xml).ConfigureAwait(false); await File.WriteAllTextAsync(tempManifestPath, xml.ToString(SaveOptions.None), cancellationToken); fileListBuilder.AddManifest(tempManifestPath); } await File.WriteAllTextAsync(tempFileList, fileListBuilder.ToString(), cancellationToken).ConfigureAwait(false); var sdk = new MakeAppxWrapper(); await sdk.PackPackageFiles(tempFileList, this.OutputPath.CurrentValue, this.Compress.CurrentValue, this.Validate.CurrentValue, cancellationToken, progress1).ConfigureAwait(false); if (this.Sign.CurrentValue) { var manager = await this.signingManagerFactory.GetProxyFor(SelfElevationLevel.HighestAvailable, cancellationToken).ConfigureAwait(false); string timeStampUrl; switch (this.SelectedCertificate.TimeStampSelectionMode.CurrentValue) { case TimeStampSelectionMode.None: timeStampUrl = null; break; case TimeStampSelectionMode.Auto: timeStampUrl = "auto"; break; case TimeStampSelectionMode.Url: timeStampUrl = this.SelectedCertificate.TimeStamp.CurrentValue; break; default: throw new ArgumentOutOfRangeException(); } switch (this.SelectedCertificate.Store.CurrentValue) { case CertificateSource.Personal: await manager.SignPackageWithInstalled(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.SelectedPersonalCertificate.CurrentValue?.Model, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; case CertificateSource.Pfx: await manager.SignPackageWithPfx(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.PfxPath.CurrentValue, this.SelectedCertificate.Password.CurrentValue, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; case CertificateSource.DeviceGuard: await manager.SignPackageWithDeviceGuardFromUi(this.OutputPath.CurrentValue, this.SelectedCertificate.DeviceGuard.CurrentValue, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false); break; } } if (this.RemoveDirectory.CurrentValue) { ExceptionGuard.Guard(() => Directory.Delete(this.InputPath.CurrentValue, true)); } return(true); } finally { foreach (var tempFile in temporaryFiles) { ExceptionGuard.Guard(() => File.Delete(tempFile)); } } }
public async Task <string> CalculateSignatureHashAsync(Uri url, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = null) { using var wrappedProgress = new WrappedProgress(progress); var progressForDownload = wrappedProgress.GetChildProgress(85); var progressForHashing = wrappedProgress.GetChildProgress(15); var webRequest = (HttpWebRequest)WebRequest.Create(url); using var response = webRequest.GetResponse(); var tempFileName = Path.Combine(Path.GetTempPath(), "msixhero-" + Guid.NewGuid().ToString("N").Substring(0, 8) + FileConstants.MsixExtension); try { // ReSharper disable once UseAwaitUsing using (var fs = File.OpenWrite(tempFileName)) { var buffer = new byte[4096]; await using var responseStream = response.GetResponseStream(); if (responseStream == null) { throw new InvalidOperationException("Could not download the file."); } int read; var totalSize = response.ContentLength; var processed = 0L; var lastFlush = 0L; const long bufferFlushing = 1024 * 1024 * 10; // 10 MB while ((read = await responseStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) > 0) { processed += read; if (totalSize > 0) { var p = (int)(100.0 * processed / totalSize); progressForDownload.Report(new ProgressData(p, $"Downloading... ({p}%)")); } cancellationToken.ThrowIfCancellationRequested(); await fs.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false); if (processed + bufferFlushing > lastFlush) { await fs.FlushAsync(cancellationToken).ConfigureAwait(false); lastFlush = processed; } } await fs.FlushAsync(cancellationToken).ConfigureAwait(false); } return(await this.CalculateSignatureHashAsync(new FileInfo(tempFileName), cancellationToken, progressForHashing).ConfigureAwait(false)); } finally { File.Delete(tempFileName); } }
public async Task CreateVolume(string packagePath, string volumePath, uint vhdSize, bool extractCertificate, bool generateScripts, CancellationToken cancellationToken = default, IProgress <ProgressData> progressReporter = null) { if (packagePath == null) { throw new ArgumentNullException(nameof(packagePath)); } if (volumePath == null) { throw new ArgumentNullException(nameof(packagePath)); } var packageFileInfo = new FileInfo(packagePath); if (!packageFileInfo.Exists) { throw new FileNotFoundException($"File {packagePath} does not exist.", packagePath); } var volumeFileInfo = new FileInfo(volumePath); if (volumeFileInfo.Directory != null && !volumeFileInfo.Directory.Exists) { volumeFileInfo.Directory.Create(); } var tmpPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".vhd"); using (var progress = new WrappedProgress(progressReporter)) { // ReSharper disable once UnusedVariable var progressSize = vhdSize <= 0 ? progress.GetChildProgress(30) : null; var progressStopService = progress.GetChildProgress(10); var progressInitializeDisk = progress.GetChildProgress(100); // var progressNewPartition = progress.GetChildProgress(30); // var progressFormatVolume = progress.GetChildProgress(80); var progressStartService = progress.GetChildProgress(10); var progressExpand = progress.GetChildProgress(120); var progressScripts = generateScripts ? progress.GetChildProgress(10) : null; try { var minimumSize = vhdSize > 0 ? 1024 * 1024 * vhdSize : await GetVhdSize(packagePath, cancellationToken : cancellationToken).ConfigureAwait(false); bool requiresRestart; try { requiresRestart = await StopService(cancellationToken, progressStopService).ConfigureAwait(false); } catch (Exception) { requiresRestart = false; } Guid volumeGuid; var wrapper = new DiskPartWrapper(); string pkgFullName; try { var allDrives = DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveFormat == "NTFS").Select(d => d.Name.ToLowerInvariant()).ToArray(); var existing = await this.GetVolumeIdentifiers().ConfigureAwait(false); await wrapper.CreateVhdAndAssignDriveLetter(tmpPath, minimumSize, cancellationToken, progressInitializeDisk).ConfigureAwait(false); var newVolumes = (await this.GetVolumeIdentifiers().ConfigureAwait(false)).Except(existing).ToArray(); var newDrives = DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveFormat == "NTFS").Select(d => d.Name.ToLowerInvariant()).Except(allDrives).ToArray(); if (newDrives.Length != 1 || newVolumes.Length != 1) { throw new InvalidOperationException("Could not mount the drive."); } volumeGuid = newVolumes[0]; cancellationToken.ThrowIfCancellationRequested(); pkgFullName = await this.ExpandMsix(packagePath, newDrives.First() + Path.GetFileNameWithoutExtension(packagePath), cancellationToken, progressExpand).ConfigureAwait(false); } finally { await wrapper.DismountVhd(tmpPath, cancellationToken).ConfigureAwait(false); if (requiresRestart) { try { await StartService(cancellationToken, progressStartService).ConfigureAwait(false); } catch (Exception e) { Logger.Warn(e, "Could not restart the service ShellHWDetection."); } } } if (File.Exists(tmpPath)) { if (generateScripts) { await CreateScripts(volumeFileInfo.FullName, Path.GetFileNameWithoutExtension(packagePath), volumeGuid, pkgFullName, cancellationToken, progressScripts).ConfigureAwait(false); } await CreateJson(volumeFileInfo.FullName, Path.GetFileNameWithoutExtension(packagePath), volumeGuid, pkgFullName, cancellationToken, progressScripts).ConfigureAwait(false); if (extractCertificate) { ISigningManager certMgr = this.signingManager; if (certMgr == null) { certMgr = await this.managerFactory.GetProxyFor(SelfElevationLevel.AsInvoker, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); // ReSharper disable once AssignNullToNotNullAttribute await certMgr.ExtractCertificateFromMsix(packagePath, Path.Combine(volumeFileInfo.DirectoryName, Path.GetFileNameWithoutExtension(volumeFileInfo.FullName)) + ".cer", cancellationToken).ConfigureAwait(false); } File.Move(tmpPath, volumeFileInfo.FullName, true); } } finally { if (File.Exists(tmpPath)) { File.Delete(tmpPath); } } } }