public EditPackageVersionReadMeRequest(PackageEdit pendingMetadata) { var metadata = pendingMetadata ?? new PackageEdit(); ReadMeState = metadata.ReadMeState; ReadMe = new ReadMeRequest(); }
private void ProcessPackageEdits(int packageKey) { // Create a fresh entities context so that we work in isolation var entitiesContext = new EntitiesContext(ConnectionString.ConnectionString, readOnly: false); // Get the list of edits for this package // Do edit with a 'most recent edit to this package wins - other edits are deleted' strategy. var editsForThisPackage = entitiesContext.Set <PackageEdit>() .Where(pe => pe.PackageKey == packageKey && pe.TriedCount < 3) .Include(pe => pe.Package) .Include(pe => pe.Package.PackageRegistration) .Include(pe => pe.User) .OrderByDescending(pe => pe.Timestamp) .ToList(); // List of Work to do: // 1) Backup old blob, if the original has not been backed up yet // 2) Downloads blob, create new NUPKG locally // 3) Upload blob // 4) Update the database PackageEdit edit = editsForThisPackage.First(); var blobClient = StorageAccount.CreateCloudBlobClient(); var packagesContainer = Util.GetPackagesBlobContainer(blobClient); var latestPackageFileName = Util.GetPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageFileName = Util.GetBackupOfOriginalPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageBackupBlob = packagesContainer.GetBlockBlobReference(originalPackageFileName); var latestPackageBlob = packagesContainer.GetBlockBlobReference(latestPackageFileName); var edits = new List <Action <ManifestMetadata> > { (m) => { m.Authors = edit.Authors; }, (m) => { m.Copyright = edit.Copyright; }, (m) => { m.Description = edit.Description; }, (m) => { m.IconUrl = edit.IconUrl; }, (m) => { m.LicenseUrl = edit.LicenseUrl; }, (m) => { m.ProjectUrl = edit.ProjectUrl; }, (m) => { m.ReleaseNotes = edit.ReleaseNotes; }, (m) => { m.RequireLicenseAcceptance = edit.RequiresLicenseAcceptance; }, (m) => { m.Summary = edit.Summary; }, (m) => { m.Title = edit.Title; }, (m) => { m.Tags = edit.Tags; }, }; Log.Info( "Processing Edit Key={0}, PackageId={1}, Version={2}, User={3}", edit.Key, edit.Package.PackageRegistration.Id, edit.Package.Version, edit.User.Username); if (!WhatIf) { edit.TriedCount += 1; int nr = entitiesContext.SaveChanges(); if (nr != 1) { throw new Exception( String.Format("Something went terribly wrong, only one entity should be updated but actually {0} entities were updated", nr)); } } try { ArchiveOriginalPackageBlob(originalPackageBackupBlob, latestPackageBlob); using (var readWriteStream = new MemoryStream()) { // Download to memory CloudBlockBlob downloadSourceBlob = WhatIf ? latestPackageBlob : originalPackageBackupBlob; Log.Info("Downloading original package blob to memory {0}", downloadSourceBlob.Name); downloadSourceBlob.DownloadToStream(readWriteStream); // Rewrite in memory Log.Info("Rewriting nupkg package in memory", downloadSourceBlob.Name); NupkgRewriter.RewriteNupkgManifest(readWriteStream, edits); // Get updated hash code, and file size Log.Info("Computing updated hash code of memory stream"); var newPackageFileSize = readWriteStream.Length; var hashAlgorithm = HashAlgorithm.Create("SHA512"); byte[] hashBytes = hashAlgorithm.ComputeHash(readWriteStream.GetBuffer()); var newHash = Convert.ToBase64String(hashBytes); if (!WhatIf) { // Snapshot the blob var blobSnapshot = latestPackageBlob.CreateSnapshot(); // Build up the changes in the entities context edit.Apply(hashAlgorithm: "SHA512", hash: newHash, packageFileSize: newPackageFileSize); foreach (var eachEdit in editsForThisPackage) { entitiesContext.DeleteOnCommit(eachEdit); } // Upload the blob before doing SaveChanges(). If blob update fails, we won't do SaveChanges() and the edit can be retried. // If SaveChanges() fails we can undo the blob upload. try { Log.Info("Uploading blob from memory {0}", latestPackageBlob.Name); readWriteStream.Position = 0; latestPackageBlob.UploadFromStream(readWriteStream); } catch (Exception e) { Log.Error("(error) - package edit blob update failed."); Log.ErrorException("(exception)", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); throw; // To handler block that will record error in DB } try { // SaveChanges tries to commit changes to DB entitiesContext.SaveChanges(); } catch (Exception e) { // Commit changes to DB probably failed. // Since our blob update wasn't part of the transaction (and doesn't AFAIK have a 'commit()' operator we can utilize for the type of blobs we are using) // try, (single attempt) to roll back the blob update by restoring the previous snapshot. Log.Error("(error) - package edit DB update failed. Trying to roll back the blob to its previous snapshot."); Log.ErrorException("(exception)", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); try { latestPackageBlob.StartCopyFromBlob(blobSnapshot); } catch (Exception e2) { // If blob rollback fails it is not be the end of the world // - the package metadata mismatches the edit now, // but there should still an edit in the queue, waiting to be rerun and put everything back in synch. Log.Error("(error) - rolling back the package blob to its previous snapshot failed."); Log.ErrorException("(exception)", e2); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); } throw; // To handler block that will record error in DB } } } } catch (Exception e) { if (!WhatIf) { try { Log.Info("Storing the error on package edit with key {0}", edit.Key); // Try to record the error into the PackageEdit database record // so that we can actually diagnose failures. // This must be done on a fresh context to ensure no conflicts. var errorContext = new EntitiesContext(ConnectionString.ConnectionString, readOnly: false); var errorEdit = errorContext.Set <PackageEdit>().Where(pe => pe.Key == edit.Key).FirstOrDefault(); if (errorEdit != null) { errorEdit.LastError = string.Format("{0} : {1}", e.GetType(), e); errorContext.SaveChanges(); } else { Log.Info("The package edit with key {0} couldn't be found. It was likely canceled and deleted.", edit.Key); } } catch (Exception errorException) { Log.ErrorException("(error) - couldn't save the last error on the edit that was being applied.", errorException); } } } }
public override void Link() { VirtualRoot.Window <ShowDialogWindowCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { DialogWindow.ShowDialog(message: message.Message, title: message.Title, onYes: message.OnYes, icon: message.Icon); }); }); VirtualRoot.Window <ShowQQGroupQrCodeCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { QQGroupQrCode.ShowWindow(); }); }); VirtualRoot.Window <ShowCalcCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { Calc.ShowWindow(message.CoinVm); }); }); VirtualRoot.Window <ShowFileDownloaderCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { FileDownloader.ShowWindow(message.DownloadFileUrl, message.FileTitle, message.DownloadComplete); }); }); VirtualRoot.Window <ShowAboutPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { AboutPage.ShowWindow(); }); }); VirtualRoot.Window <ShowKernelOutputPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelOutputPage.ShowWindow(message.SelectedKernelOutputVm); }); }); VirtualRoot.Window <ShowKernelInputPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelInputPage.ShowWindow(); }); }); VirtualRoot.Window <ShowGroupPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { GroupPage.ShowWindow(); }); }); VirtualRoot.Window <ShowSysDicPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { SysDicPage.ShowWindow(); }); }); VirtualRoot.Window <ShowVirtualMemoryCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { VirtualMemory.ShowWindow(); }); }); VirtualRoot.Window <ShowRestartWindowsCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { RestartWindows.ShowDialog(); }); }); VirtualRoot.Window <ShowNotificationSampleCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { NotificationSample.ShowWindow(); }); }); VirtualRoot.Window <ShowOuterPropertyCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { OuterProperty.ShowWindow(); }); }); VirtualRoot.Window <ShowInnerPropertyCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { InnerProperty.ShowWindow(); }); }); VirtualRoot.Window <ShowUserPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { UserPage.ShowWindow(); }); }); VirtualRoot.Window <ShowKernelDownloaderCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelDownloading.ShowWindow(message.KernelId, message.DownloadComplete); }); }); VirtualRoot.Window <EnvironmentVariableEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { EnvironmentVariableEdit.ShowWindow(message.CoinKernelVm, message.EnvironmentVariable); }); }); VirtualRoot.Window <InputSegmentEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { InputSegmentEdit.ShowWindow(message.CoinKernelVm, message.Segment); }); }); VirtualRoot.Window <CoinKernelEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { CoinKernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <CoinEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { CoinEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <ShowContainerWindowCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { ContainerWindow window = ContainerWindow.GetWindow(message.Vm); window?.ShowWindow(); }); }); VirtualRoot.Window <GroupEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { GroupEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <KernelInputEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelInputEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <KernelOutputFilterEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelOutputFilterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <KernelOutputTranslaterEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelOutputTranslaterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <KernelOutputEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelOutputEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <ShowPackagesWindowCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { PackagesWindow.ShowWindow(); }); }); VirtualRoot.Window <KernelEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { KernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <ShowLogColorCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { LogColor.ShowWindow(); }); }); VirtualRoot.Window <ShowGpuProfilesPageCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { GpuProfilesPage.ShowWindow(message.MinerClientsWindowVm); }); }); VirtualRoot.Window <PackageEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { PackageEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <PoolKernelEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { PoolKernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <PoolEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { PoolEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <SysDicItemEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { SysDicItemEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <SysDicEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { SysDicEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <UserEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { UserEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.Window <WalletEditCommand>(LogEnum.DevConsole, action: message => { UIThread.Execute(() => { WalletEdit.ShowWindow(message.FormType, message.Source); }); }); }
public override void Link() { VirtualRoot.BuildCmdPath <ShowDialogWindowCommand>(action: message => { UIThread.Execute(() => { DialogWindow.ShowDialog(new DialogWindowViewModel(message: message.Message, title: message.Title, onYes: message.OnYes, icon: message.Icon)); }); }); VirtualRoot.BuildCmdPath <ShowQQGroupQrCodeCommand>(action: message => { UIThread.Execute(() => { QQGroupQrCode.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowCalcCommand>(action: message => { UIThread.Execute(() => { Calc.ShowWindow(message.CoinVm); }); }); VirtualRoot.BuildCmdPath <ShowLocalIpsCommand>(action: message => { UIThread.Execute(() => { LocalIpConfig.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowEthNoDevFeeCommand>(action: message => { UIThread.Execute(() => { EthNoDevFeeEdit.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowCalcConfigCommand>(action: message => { UIThread.Execute(() => { CalcConfig.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowMinerClientsWindowCommand>(action: message => { UIThread.Execute(() => { MinerClientsWindow.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowNTMinerUpdaterConfigCommand>(action: message => { UIThread.Execute(() => { NTMinerUpdaterConfig.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowAboutPageCommand>(action: message => { UIThread.Execute(() => { AboutPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowKernelOutputPageCommand>(action: message => { UIThread.Execute(() => { KernelOutputPage.ShowWindow(message.SelectedKernelOutputVm); }); }); VirtualRoot.BuildCmdPath <ShowKernelInputPageCommand>(action: message => { UIThread.Execute(() => { KernelInputPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowTagBrandCommand>(action: message => { if (NTMinerRoot.IsBrandSpecified) { return; } BrandTag.ShowWindow(); }); VirtualRoot.BuildCmdPath <ShowCoinPageCommand>(action: message => { UIThread.Execute(() => { CoinPage.ShowWindow(message.CurrentCoin, message.TabType); }); }); VirtualRoot.BuildCmdPath <ShowGroupPageCommand>(action: message => { UIThread.Execute(() => { GroupPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowSysDicPageCommand>(action: message => { UIThread.Execute(() => { SysDicPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowVirtualMemoryCommand>(action: message => { UIThread.Execute(() => { VirtualMemory.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowRestartWindowsCommand>(action: message => { UIThread.Execute(() => { RestartWindows.ShowDialog(); }); }); VirtualRoot.BuildCmdPath <ShowNotificationSampleCommand>(action: message => { UIThread.Execute(() => { NotificationSample.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowPropertyCommand>(action: message => { UIThread.Execute(() => { Property.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowChartsWindowCommand>(action: message => { UIThread.Execute(() => { ChartsWindow.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowOverClockDataPageCommand>(action: message => { UIThread.Execute(() => { OverClockDataPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowNTMinerWalletPageCommand>(action: message => { UIThread.Execute(() => { NTMinerWalletPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowMessagePathIdsCommand>(action: message => { UIThread.Execute(() => { MessagePathIds.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowUserPageCommand>(action: message => { UIThread.Execute(() => { UserPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowRemoteDesktopLoginDialogCommand>(action: message => { RemoteDesktopLogin.ShowWindow(message.Vm); }); VirtualRoot.BuildCmdPath <ShowKernelsWindowCommand>(action: message => { UIThread.Execute(() => { KernelsWindow.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowKernelDownloaderCommand>(action: message => { UIThread.Execute(() => { KernelDownloading.ShowWindow(message.KernelId, message.DownloadComplete); }); }); VirtualRoot.BuildCmdPath <EnvironmentVariableEditCommand>(action: message => { UIThread.Execute(() => { EnvironmentVariableEdit.ShowWindow(message.CoinKernelVm, message.EnvironmentVariable); }); }); VirtualRoot.BuildCmdPath <InputSegmentEditCommand>(action: message => { UIThread.Execute(() => { InputSegmentEdit.ShowWindow(message.CoinKernelVm, message.Segment); }); }); VirtualRoot.BuildCmdPath <CoinKernelEditCommand>(action: message => { UIThread.Execute(() => { CoinKernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <CoinEditCommand>(action: message => { UIThread.Execute(() => { CoinEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ColumnsShowEditCommand>(action: message => { UIThread.Execute(() => { ColumnsShowEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ShowContainerWindowCommand>(action: message => { UIThread.Execute(() => { ContainerWindow window = ContainerWindow.GetWindow(message.Vm); window?.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowSpeedChartsCommand>(action: message => { UIThread.Execute(() => { SpeedCharts.ShowWindow(message.GpuSpeedVm); }); }); VirtualRoot.BuildCmdPath <ShowFileWriterPageCommand>(action: message => { UIThread.Execute(() => { FileWriterPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <FileWriterEditCommand>(action: message => { UIThread.Execute(() => { FileWriterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ShowFragmentWriterPageCommand>(action: message => { UIThread.Execute(() => { FragmentWriterPage.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <FragmentWriterEditCommand>(action: message => { UIThread.Execute(() => { FragmentWriterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <GroupEditCommand>(action: message => { UIThread.Execute(() => { GroupEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <KernelInputEditCommand>(action: message => { UIThread.Execute(() => { KernelInputEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <KernelOutputFilterEditCommand>(action: message => { UIThread.Execute(() => { KernelOutputFilterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <KernelOutputTranslaterEditCommand>(action: message => { UIThread.Execute(() => { KernelOutputTranslaterEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <KernelOutputEditCommand>(action: message => { UIThread.Execute(() => { KernelOutputEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ShowPackagesWindowCommand>(action: message => { UIThread.Execute(() => { PackagesWindow.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <KernelEditCommand>(action: message => { UIThread.Execute(() => { KernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ShowLogColorCommand>(action: message => { UIThread.Execute(() => { LogColor.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <ShowMinerClientSettingCommand>(action: message => { UIThread.Execute(() => { MinerClientSetting.ShowWindow(message.Vm); }); }); VirtualRoot.BuildCmdPath <ShowMinerNamesSeterCommand>(action: message => { UIThread.Execute(() => { MinerNamesSeter.ShowWindow(message.Vm); }); }); VirtualRoot.BuildCmdPath <ShowGpuProfilesPageCommand>(action: message => { UIThread.Execute(() => { GpuProfilesPage.ShowWindow(message.MinerClientsWindowVm); }); }); VirtualRoot.BuildCmdPath <ShowMinerClientAddCommand>(action: message => { UIThread.Execute(() => { MinerClientAdd.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <MinerGroupEditCommand>(action: message => { UIThread.Execute(() => { MinerGroupEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <NTMinerWalletEditCommand>(action: message => { UIThread.Execute(() => { NTMinerWalletEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <MineWorkEditCommand>(action: message => { UIThread.Execute(() => { MineWorkEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <OverClockDataEditCommand>(action: message => { UIThread.Execute(() => { OverClockDataEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <PackageEditCommand>(action: message => { UIThread.Execute(() => { PackageEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <PoolKernelEditCommand>(action: message => { UIThread.Execute(() => { PoolKernelEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <PoolEditCommand>(action: message => { UIThread.Execute(() => { PoolEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <ShowControlCenterHostConfigCommand>(action: message => { UIThread.Execute(() => { ControlCenterHostConfig.ShowWindow(); }); }); VirtualRoot.BuildCmdPath <SysDicItemEditCommand>(action: message => { UIThread.Execute(() => { SysDicItemEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <SysDicEditCommand>(action: message => { UIThread.Execute(() => { SysDicEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <UserEditCommand>(action: message => { UIThread.Execute(() => { UserEdit.ShowWindow(message.FormType, message.Source); }); }); VirtualRoot.BuildCmdPath <WalletEditCommand>(action: message => { UIThread.Execute(() => { WalletEdit.ShowWindow(message.FormType, message.Source); }); }); }
private async Task ApplyEdit(PackageEdit edit) { // Download the original file string originalPath = null; try { string directory = Path.Combine(TempDirectory, edit.Id, edit.Version); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } originalPath = Path.Combine(directory, "original.nupkg"); var sourceBlob = SourceContainer.GetBlockBlobReference( StorageHelpers.GetPackageBlobName(edit.Id, edit.Version)); Log.DownloadingOriginal(edit.Id, edit.Version); await sourceBlob.DownloadToFileAsync(originalPath, FileMode.Create); Log.DownloadedOriginal(edit.Id, edit.Version); // Check that a backup exists var backupBlob = BackupsContainer.GetBlockBlobReference( StorageHelpers.GetPackageBackupBlobName(edit.Id, edit.Version, edit.Hash)); if (!WhatIf && !await backupBlob.ExistsAsync()) { Log.BackingUpOriginal(edit.Id, edit.Version); await backupBlob.UploadFromFileAsync(originalPath, FileMode.Open); Log.BackedUpOriginal(edit.Id, edit.Version); } // Load the zip file and find the manifest using (var originalStream = File.Open(originalPath, FileMode.Open, FileAccess.ReadWrite)) using (var archive = new ZipArchive(originalStream, ZipArchiveMode.Update)) { // Find the nuspec var nuspecEntries = archive.Entries.Where(e => ManifestSelector.IsMatch(e.FullName)).ToArray(); if (nuspecEntries.Length == 0) { throw new InvalidDataException(String.Format( CultureInfo.CurrentCulture, Strings.HandlePackageEditsJob_MissingManifest, edit.Id, edit.Version, backupBlob.Uri.AbsoluteUri)); } else if (nuspecEntries.Length > 1) { throw new InvalidDataException(String.Format( CultureInfo.CurrentCulture, Strings.HandlePackageEditsJob_MultipleManifests, edit.Id, edit.Version, backupBlob.Uri.AbsoluteUri)); } // We now have the nuspec var manifestEntry = nuspecEntries.Single(); // Load the manifest with a constrained stream Log.RewritingPackage(edit.Id, edit.Version); Manifest manifest; using (var manifestStream = manifestEntry.Open()) { manifest = Manifest.ReadFrom(manifestStream, validateSchema: false); // Modify the manifest as per the edit edit.ApplyTo(manifest.Metadata); // Save the manifest back manifestStream.Seek(0, SeekOrigin.Begin); manifestStream.SetLength(0); manifest.Save(manifestStream); } Log.RewrotePackage(edit.Id, edit.Version); } // Snapshot the original blob Log.SnapshottingBlob(edit.Id, edit.Version, sourceBlob.Uri.AbsoluteUri); var sourceSnapshot = await sourceBlob.CreateSnapshotAsync(); Log.SnapshottedBlob(edit.Id, edit.Version, sourceBlob.Uri.AbsoluteUri, sourceSnapshot.Uri.AbsoluteUri); // Upload the updated file Log.UploadingModifiedPackage(edit.Id, edit.Version, sourceBlob.Uri.AbsoluteUri); await sourceBlob.UploadFromFileAsync(originalPath, FileMode.Open); Log.UploadedModifiedPackage(edit.Id, edit.Version, sourceBlob.Uri.AbsoluteUri); // Calculate new size and hash string hash; long size; using (var originalStream = File.OpenRead(originalPath)) { size = originalStream.Length; var hashAlgorithm = HashAlgorithm.Create(HashAlgorithmName); hash = Convert.ToBase64String( hashAlgorithm.ComputeHash(originalStream)); } // Update the database try { Log.UpdatingDatabase(edit.Id, edit.Version); using (var connection = await PackageDatabase.ConnectTo()) { var parameters = new DynamicParameters(new { edit.Authors, edit.Copyright, edit.Description, edit.IconUrl, edit.LicenseUrl, edit.ProjectUrl, edit.ReleaseNotes, edit.RequiresLicenseAcceptance, edit.Summary, edit.Title, edit.Tags, edit.Key, edit.PackageKey, edit.UserKey, PackageFileSize = size, Hash = hash, HashAlgorithm = HashAlgorithmName }); // Prep SQL for merging in authors StringBuilder loadAuthorsSql = new StringBuilder(); var authors = edit.Authors.Split(','); for (int i = 0; i < authors.Length; i++) { loadAuthorsSql.Append("INSERT INTO [PackageAuthors]([PackageKey],[Name]) VALUES(@PackageKey, @Author" + i.ToString() + ")"); parameters.Add("Author" + i.ToString(), authors[i]); } await connection.QueryAsync <int>(@" BEGIN TRANSACTION -- Form a comma-separated list of authors DECLARE @existingAuthors nvarchar(MAX) SELECT @existingAuthors = COALESCE(@existingAuthors + ',', '') + Name FROM PackageAuthors WHERE PackageKey = @PackageKey -- Copy packages data to package history table INSERT INTO [PackageHistories] SELECT [Key] AS PackageKey, @UserKey AS UserKey, GETUTCDATE() AS Timestamp, Title, @existingAuthors AS Authors, Copyright, Description, IconUrl, LicenseUrl, ProjectUrl, ReleaseNotes, RequiresLicenseAcceptance, Summary, Tags, Hash, HashAlgorithm, PackageFileSize, LastUpdated, Published FROM [Packages] WHERE [Key] = @PackageKey -- Update the packages table UPDATE [Packages] SET Copyright = @Copyright, Description = @Description, IconUrl = @IconUrl, LicenseUrl = @LicenseUrl, ProjectUrl = @ProjectUrl, ReleaseNotes = @ReleaseNotes, RequiresLicenseAcceptance = @RequiresLicenseAcceptance, Summary = @Summary, Title = @Title, Tags = @Tags, LastEdited = GETUTCDATE(), LastUpdated = GETUTCDATE(), UserKey = @UserKey, Hash = @Hash, HashAlgorithm = @HashAlgorithm, PackageFileSize = @PackageFileSize, FlattenedAuthors = @Authors WHERE [Key] = @PackageKey -- Update Authors DELETE FROM [PackageAuthors] WHERE PackageKey = @PackageKey " + loadAuthorsSql.ToString() + @" -- Clean this edit and all previous edits. DELETE FROM [PackageEdits] WHERE [PackageKey] = @PackageKey AND [Key] <= @Key " + (WhatIf ? "ROLLBACK TRANSACTION" : "COMMIT TRANSACTION"), parameters); } Log.UpdatedDatabase(edit.Id, edit.Version); } catch (Exception) { // Error occurred while updaing database, roll back the blob to the snapshot // Can't do "await" in a catch block, but this should be pretty quick since it just starts the copy Log.RollingBackBlob(edit.Id, edit.Version, sourceSnapshot.Uri.AbsoluteUri, sourceBlob.Uri.AbsoluteUri); sourceBlob.StartCopyFromBlob(sourceSnapshot); Log.RolledBackBlob(edit.Id, edit.Version, sourceSnapshot.Uri.AbsoluteUri, sourceBlob.Uri.AbsoluteUri); throw; } Log.DeletingSnapshot(edit.Id, edit.Version, sourceSnapshot.Uri.AbsoluteUri); await sourceSnapshot.DeleteAsync(); Log.DeletedSnapshot(edit.Id, edit.Version, sourceSnapshot.Uri.AbsoluteUri); } finally { if (!String.IsNullOrEmpty(originalPath) && File.Exists(originalPath)) { File.Delete(originalPath); } } }
private void ProcessPackageEdits(IEnumerable <PackageEdit> editsForThisPackage, EntitiesContext entitiesContext) { // List of Work to do: // 1) Backup old blob, if the original has not been backed up yet // 2) Downloads blob, create new NUPKG locally // 3) Upload blob // 4) Update the database PackageEdit edit = editsForThisPackage.OrderByDescending(pe => pe.Timestamp).First(); var blobClient = StorageAccount.CreateCloudBlobClient(); var packagesContainer = Util.GetPackagesBlobContainer(blobClient); var latestPackageFileName = Util.GetPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageFileName = Util.GetBackupOfOriginalPackageFileName(edit.Package.PackageRegistration.Id, edit.Package.Version); var originalPackageBackupBlob = packagesContainer.GetBlockBlobReference(originalPackageFileName); var latestPackageBlob = packagesContainer.GetBlockBlobReference(latestPackageFileName); var edits = new List <Action <ManifestMetadata> > { (m) => { m.Authors = edit.Authors; }, (m) => { m.Copyright = edit.Copyright; }, (m) => { m.Description = edit.Description; }, (m) => { m.IconUrl = edit.IconUrl; }, (m) => { m.LicenseUrl = edit.LicenseUrl; }, (m) => { m.ProjectUrl = edit.ProjectUrl; }, (m) => { m.ReleaseNotes = edit.ReleaseNotes; }, (m) => { m.RequireLicenseAcceptance = edit.RequiresLicenseAcceptance; }, (m) => { m.Summary = edit.Summary; }, (m) => { m.Title = edit.Title; }, (m) => { m.Tags = edit.Tags; }, }; Log.Info( "Processing Edit Key={0}, PackageId={1}, Version={2}", edit.Key, edit.Package.PackageRegistration.Id, edit.Package.Version); if (!WhatIf) { edit.TriedCount += 1; int nr = entitiesContext.SaveChanges(); if (nr != 1) { throw new ApplicationException( String.Format("Something went terribly wrong, only one entity should be updated but actually {0} entities were updated", nr)); } } ArchiveOriginalPackageBlob(originalPackageBackupBlob, latestPackageBlob); using (var readWriteStream = new MemoryStream()) { // Download to memory CloudBlockBlob downloadSourceBlob = WhatIf ? latestPackageBlob : originalPackageBackupBlob; Log.Info("Downloading original package blob to memory {0}", downloadSourceBlob.Name); downloadSourceBlob.DownloadToStream(readWriteStream); // Rewrite in memory Log.Info("Rewriting nupkg package in memory", downloadSourceBlob.Name); NupkgRewriter.RewriteNupkgManifest(readWriteStream, edits); // Get updated hash code, and file size Log.Info("Computing updated hash code of memory stream"); var newPackageFileSize = readWriteStream.Length; var hashAlgorithm = HashAlgorithm.Create("SHA512"); byte[] hashBytes = hashAlgorithm.ComputeHash(readWriteStream.GetBuffer()); var newHash = Convert.ToBase64String(hashBytes); if (!WhatIf) { // Snapshot the blob var blobSnapshot = latestPackageBlob.CreateSnapshot(); // Start Transaction: Complete the edit in the gallery DB. // Use explicit SQL transactions instead of EF operation-grouping // so that we can manually roll the transaction back on a blob related failure. ObjectContext objectContext = (entitiesContext as IObjectContextAdapter).ObjectContext; ((objectContext.Connection) as EntityConnection).Open(); // must open in order to begin transaction using (EntityTransaction transaction = ((objectContext.Connection) as EntityConnection).BeginTransaction()) { edit.Apply(hashAlgorithm: "SHA512", hash: newHash, packageFileSize: newPackageFileSize); // Add to transaction: delete all the pending edits of this package. foreach (var eachEdit in editsForThisPackage) { entitiesContext.DeleteOnCommit(eachEdit); } entitiesContext.SaveChanges(); // (transaction is still not committed, but do some EF legwork up-front of modifying the blob) try { // Reupload blob Log.Info("Uploading blob from memory {0}", latestPackageBlob.Name); readWriteStream.Position = 0; latestPackageBlob.UploadFromStream(readWriteStream); } catch (Exception e) { // Uploading the updated nupkg failed. // Rollback the transaction, which restores the Edit to PackageEdits so it can be attempted again. Log.Error("(error) - package edit blob update failed. Rolling back the DB transaction."); Log.ErrorException("(exception", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); transaction.Rollback(); return; } try { transaction.Commit(); } catch (Exception e) { // Commit changes to DB failed. // Since our blob update wasn't part of the transaction (and doesn't AFAIK have a 'commit()' operator we can utilize for the type of blobs we are using) // try, (single attempt) to roll back the blob update by restoring the previous snapshot. Log.Error("(error) - package edit DB update failed. Trying to roll back the blob to its previous snapshot."); Log.ErrorException("(exception", e); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); try { latestPackageBlob.StartCopyFromBlob(blobSnapshot); } catch (Exception e2) { // In this case it may not be the end of the world - the package metadata mismatches the edit now, // but there's still an edit in the queue, waiting to be rerun and put everything back in synch. Log.Error("(error) - rolling back the package blob to its previous snapshot failed."); Log.ErrorException("(exception", e2); Log.Error("(note) - blob snapshot URL = " + blobSnapshot.Uri); } } } } } }
public override void BuildPaths() { var location = this.GetType(); VirtualRoot.AddCmdPath <ShowDialogWindowCommand>(action: message => { UIThread.Execute(() => { DialogWindow.ShowSoftDialog(new DialogWindowViewModel(message: message.Message, title: message.Title, onYes: message.OnYes, icon: message.Icon)); }); }, location: location); VirtualRoot.AddCmdPath <ShowCalcCommand>(action: message => { UIThread.Execute(() => { Calc.ShowWindow(message.CoinVm); }); }, location: location); VirtualRoot.AddCmdPath <ShowLocalIpsCommand>(action: message => { UIThread.Execute(() => { MinerClientUcs.LocalIpConfig.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowAboutPageCommand>(action: message => { UIThread.Execute(() => { AboutPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowKernelOutputPageCommand>(action: message => { UIThread.Execute(() => { KernelOutputPage.ShowWindow(message.SelectedKernelOutputVm); }); }, location: location); VirtualRoot.AddCmdPath <ShowKernelInputPageCommand>(action: message => { UIThread.Execute(() => { KernelInputPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowTagBrandCommand>(action: message => { if (NTMinerContext.IsBrandSpecified) { return; } UIThread.Execute(() => { BrandTag.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowCoinPageCommand>(action: message => { UIThread.Execute(() => { CoinPage.ShowWindow(message.CurrentCoin, message.TabType); }); }, location: location); VirtualRoot.AddCmdPath <ShowCoinGroupsCommand>(action: message => { UIThread.Execute(() => { CoinGroupPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowSysDicPageCommand>(action: message => { UIThread.Execute(() => { SysDicPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowVirtualMemoryCommand>(action: message => { UIThread.Execute(() => { MinerClientUcs.VirtualMemory.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowRestartWindowsCommand>(action: message => { UIThread.Execute(() => { RestartWindows.ShowDialog(new RestartWindowsViewModel(message.CountDownSeconds)); }); }, location: location); VirtualRoot.AddCmdPath <ShowNotificationSampleCommand>(action: message => { UIThread.Execute(() => { NotificationSample.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowPropertyCommand>(action: message => { UIThread.Execute(() => { Property.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowMessagePathIdsCommand>(action: message => { UIThread.Execute(() => { MessagePathIds.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowKernelsWindowCommand>(action: message => { UIThread.Execute(() => { KernelsWindow.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowKernelDownloaderCommand>(action: message => { UIThread.Execute(() => { KernelDownloading.ShowWindow(message.KernelId, message.DownloadComplete); }); }, location: location); VirtualRoot.AddCmdPath <EditEnvironmentVariableCommand>(action: message => { UIThread.Execute(() => { EnvironmentVariableEdit.ShowWindow(message.CoinKernelVm, message.EnvironmentVariable); }); }, location: location); VirtualRoot.AddCmdPath <EditInputSegmentCommand>(action: message => { UIThread.Execute(() => { InputSegmentEdit.ShowWindow(message.CoinKernelVm, message.Segment); }); }, location: location); VirtualRoot.AddCmdPath <EditCoinKernelCommand>(action: message => { UIThread.Execute(() => { CoinKernelEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditCoinCommand>(action: message => { UIThread.Execute(() => { CoinEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <ShowSpeedChartsCommand>(action: message => { UIThread.Execute(() => { SpeedCharts.ShowWindow(message.GpuSpeedVm); }); }, location: location); VirtualRoot.AddCmdPath <ShowFileWriterPageCommand>(action: message => { UIThread.Execute(() => { FileWriterPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <EditFileWriterCommand>(action: message => { UIThread.Execute(() => { FileWriterEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <ShowFragmentWriterPageCommand>(action: message => { UIThread.Execute(() => { FragmentWriterPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <EditFragmentWriterCommand>(action: message => { UIThread.Execute(() => { FragmentWriterEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditGroupCommand>(action: message => { UIThread.Execute(() => { GroupEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditServerMessageCommand>(action: message => { UIThread.Execute(() => { ServerMessageEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditKernelInputCommand>(action: message => { UIThread.Execute(() => { KernelInputEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditKernelOutputKeywordCommand>(action: message => { UIThread.Execute(() => { KernelOutputKeywordEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditKernelOutputTranslaterCommand>(action: message => { UIThread.Execute(() => { KernelOutputTranslaterEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditKernelOutputCommand>(action: message => { UIThread.Execute(() => { KernelOutputEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <ShowPackagesWindowCommand>(action: message => { UIThread.Execute(() => { PackagesWindow.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <EditKernelCommand>(action: message => { UIThread.Execute(() => { KernelEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditPackageCommand>(action: message => { UIThread.Execute(() => { PackageEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditPoolKernelCommand>(action: message => { UIThread.Execute(() => { PoolKernelEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditPoolCommand>(action: message => { UIThread.Execute(() => { PoolEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditSysDicItemCommand>(action: message => { UIThread.Execute(() => { SysDicItemEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditSysDicCommand>(action: message => { UIThread.Execute(() => { SysDicEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <ShowKernelOutputKeywordsCommand>(action: message => { UIThread.Execute(() => { KernelOutputKeywords.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowSignUpPageCommand>(action: message => { UIThread.Execute(() => { SignUpPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <EditWalletCommand>(action: message => { UIThread.Execute(() => { WalletEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); #region MinerStudio VirtualRoot.AddCmdPath <ShowQQGroupQrCodeCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.QQGroupQrCode.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowCalcConfigCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.CalcConfig.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerClientsWindowCommand>(action: message => { UIThread.Execute(() => { MinerStudioViews.MinerClientsWindow.ShowWindow(message.IsToggle); }); }, location: location); VirtualRoot.AddCmdPath <ShowNTMinerUpdaterConfigCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.NTMinerUpdaterConfig.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerClientFinderConfigCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MinerClientFinderConfig.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowChartsWindowCommand>(action: message => { UIThread.Execute(() => { MinerStudioViews.ChartsWindow.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowOverClockDataPageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.OverClockDataPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerStudioVirtualMemoryCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.VirtualMemory.ShowWindow(message.Vm); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerStudioLocalIpsCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.LocalIpConfig.ShowWindow(message.Vm); }); }, location: location); VirtualRoot.AddCmdPath <ShowNTMinerWalletPageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.NTMinerWalletPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowUserPageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.UserPage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowGpuNamePageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.GpuNameCounts.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowChangePassword>(action: message => { UIThread.Execute(() => { MinerStudioUcs.ChangePassword.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowWsServerNodePageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.WsServerNodePage.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <ShowRemoteDesktopLoginDialogCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.RemoteDesktopLogin.ShowWindow(message.Vm); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerClientSettingCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MinerClientSetting.ShowWindow(message.Vm); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerNamesSeterCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MinerNamesSeter.ShowWindow(message.Vm); }); }, location: location); VirtualRoot.AddCmdPath <ShowGpuProfilesPageCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.GpuProfilesPage.ShowWindow(message.MinerClientsWindowVm); }); }, location: location); VirtualRoot.AddCmdPath <ShowMinerClientAddCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MinerClientAdd.ShowWindow(); }); }, location: location); VirtualRoot.AddCmdPath <EditMinerGroupCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MinerGroupEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditNTMinerWalletCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.NTMinerWalletEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditMineWorkCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.MineWorkEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditOverClockDataCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.OverClockDataEdit.ShowWindow(message.FormType, message.Source); }); }, location: location); VirtualRoot.AddCmdPath <EditColumnsShowCommand>(action: message => { UIThread.Execute(() => { MinerStudioUcs.ColumnsShowEdit.ShowWindow(message.Source); }); }, location: location); #endregion }