private void ExportBeatmapSets(List <Beatmap> beatmaps) { if (beatmaps?.Count == 0) { _userDialogs.OkMessageBox("No beatmaps selected", "Info"); return; } var saveDirectory = _userDialogs.SelectDirectory("Select directory for exported maps", true); var beatmapSets = beatmaps.Where(b => !string.IsNullOrWhiteSpace(b.Dir)).Select(b => (Beatmap: b, FileName: OsuDownloadManager.CreateOszFileName(b))) .GroupBy(e => e.FileName).Select(e => e.First()).ToList(); if (!Directory.Exists(saveDirectory)) { return; } var backgroundWorker = new BackgroundWorker(); var stringProgress = new Progress <string>(); var percentageProgress = new Progress <int>(); using var cancelationTokenSource = new CancellationTokenSource(); var progressForm = _userDialogs.ProgressForm(stringProgress, percentageProgress); progressForm.AbortClicked += (_, __) => cancelationTokenSource.Cancel(); backgroundWorker.DoWork += (_, eventArgs) => { var cancellationToken = cancelationTokenSource.Token; var totalCount = beatmapSets.Count(); var stringProgressReporter = (IProgress <string>)stringProgress; var percentageProgressReporter = (IProgress <int>)percentageProgress; var failedMapSets = new StringBuilder(); var failedMapSetsCount = 0; for (int i = 0; i < totalCount; i++) { var beatmapset = beatmapSets[i]; if (cancellationToken.IsCancellationRequested) { progressForm.Close(); return; } stringProgressReporter.Report($"Processing map set {i + 1} of {totalCount}.{Environment.NewLine}\"{beatmapset.FileName}\""); var fileSaveLocation = Path.Combine(saveDirectory, beatmapset.FileName); if (File.Exists(fileSaveLocation)) { percentageProgressReporter.Report(Convert.ToInt32((double)(i + 1) / totalCount * 100)); continue; } var beatmapDirectory = beatmapset.Beatmap.BeatmapDirectory(); if (!Directory.Exists(beatmapDirectory)) { failedMapSets.AppendFormat("map set directory \"{0}\" doesn't exist - set skipped(mapId:{1} setId:{2} hash:{3}) {4}{4}", beatmapDirectory, beatmapset.Beatmap.MapId.ToString(), beatmapset.Beatmap.MapSetId.ToString(), beatmapset.Beatmap.Md5, Environment.NewLine); failedMapSetsCount++; } else { try { ZipFile.CreateFromDirectory(beatmapDirectory, fileSaveLocation); } catch (Exception e) { failedMapSets.AppendFormat("failed processing map set located at \"{0}\" with exception:{2}{1}{2}{2}", beatmapDirectory, e, Environment.NewLine); failedMapSetsCount++; } percentageProgressReporter.Report(Convert.ToInt32((double)(i + 1) / totalCount * 100)); } } if (failedMapSetsCount > 0) { File.WriteAllText(Path.Combine(saveDirectory, "log.txt"), failedMapSets.ToString()); stringProgressReporter.Report($"Processed {totalCount - failedMapSetsCount} of {totalCount} map sets.{Environment.NewLine}{failedMapSetsCount} map sets failed to save, see full log in log.txt file in export directory"); } else { stringProgressReporter.Report($"Processed {totalCount} map sets without issues."); } }; backgroundWorker.RunWorkerAsync(); progressForm.ShowAndBlock(); }