public override void Delete() { if (DownloadState == DownloadState.Error || DownloadState == DownloadState.Ready) { return; } try { var title = DownloadHelper.GetLegalPath(Title); var videoFile = VideoFolder.CreateFile(title + VideoExtension); if (videoFile.Exists()) { videoFile.Delete(); } if (MediaType == MediaType.Audio) { var audioFile = DownloadFolder.CreateFile(title + ".mp3"); if (audioFile.Exists()) { audioFile.Delete(); } } } catch { } base.Delete(); UpdateStatus(DownloadState.Deleted); }
public async Task DownloadMissingArchives(List <Archive> missing, bool download = true) { if (download) { foreach (var a in missing.Where(a => a.State.GetType() == typeof(ManualDownloader.State))) { var outputPath = DownloadFolder.Combine(a.Name); await a.State.Download(a, outputPath); } } await missing.Where(a => a.State.GetType() != typeof(ManualDownloader.State)) .PMap(Queue, async archive => { Info($"Downloading {archive.Name}"); var outputPath = DownloadFolder.Combine(archive.Name); if (download) { if (outputPath.Exists) { var origName = Path.GetFileNameWithoutExtension(archive.Name); var ext = Path.GetExtension(archive.Name); var uniqueKey = archive.State.PrimaryKeyString.StringSha256Hex(); outputPath = DownloadFolder.Combine(origName + "_" + uniqueKey + "_" + ext); outputPath.Delete(); } } return(await DownloadArchive(archive, download, outputPath)); }); }
//下载一个解析好的Album对象,把每张图片存入本地 private async Task donwloadAlbumObject(Album album) { //判断是否需要为相册创建单独的文件夹 StorageFolder saveFolder = DownloadFolder; if (NeedIndividualFolder) { saveFolder = await DownloadFolder.CreateFolderAsync(album.AlbumName, CreationCollisionOption.GenerateUniqueName); } int picNum = 0; foreach (string imagePageUrl in album.ImagePageUrlList) { picNum++; Picture picture = await findPictureInImagePage(album.AlbumName, picNum, imagePageUrl); album.PictureList.Add(picture); //让程序暂停,但已经开始的Task还是会完成下载。 while (IsPausing) { await Task.Delay(1000); } imageDownload(picture, saveFolder); } album.IsDownloaded = true; //album.DownloadStateIcon = Symbol.Accept; }
public async Task HashArchives() { Utils.Log("Looking for files to hash"); var allFiles = DownloadFolder.EnumerateFiles() .Concat(Game.GameLocation().EnumerateFiles()) .ToList(); var hashDict = allFiles.GroupBy(f => f.Size).ToDictionary(g => g.Key); var toHash = ModList.Archives.Where(a => hashDict.ContainsKey(a.Size)).SelectMany(a => hashDict[a.Size]).ToList(); Utils.Log($"Found {allFiles.Count} total files, {toHash.Count} matching filesize"); var hashResults = await toHash .PMap(Queue, UpdateTracker, async e => (await e.FileHashCachedAsync(), e)); HashedArchives.SetTo(hashResults .OrderByDescending(e => e.Item2.LastModified) .GroupBy(e => e.Item1) .Select(e => e.First()) .Where(x => x.Item1 != null) .Select(e => new KeyValuePair <Hash, AbsolutePath>(e.Item1 !.Value, e.Item2))); }
public async void DeleteFilesAsync() { try { if (SteamAppsFolder.Exists) { await Task.Run(() => SteamAppsFolder.Delete(true)); } if (WorkshopFolder.Exists) { await Task.Run(() => WorkshopFolder.Delete(true)); } if (DownloadFolder.Exists) { await Task.Run(() => DownloadFolder.Delete(true)); } } catch (Exception ex) { logger.Fatal(ex); SLM.RavenClient.Capture(new SharpRaven.Data.SentryEvent(ex)); } }
public override List <FileInfo> GetFileList() { try { var fileList = new List <FileInfo>(); if (IsCompressed) { fileList.Add(CompressedArchivePath); } else { fileList.AddRange(base.GetFileList()); DownloadFolder.Refresh(); if (DownloadFolder.Exists) { var downloadFiles = GetDownloadFiles(); var patchFiles = GetPatchFiles(); if (downloadFiles != null) { fileList.AddRange(downloadFiles); } if (patchFiles != null) { fileList.AddRange(patchFiles); } } WorkShopPath.Refresh(); if (WorkShopPath.Exists) { var workshopPath = GetWorkshopFiles(); fileList.AddRange(workshopPath); } FullAcfPath.Refresh(); if (FullAcfPath.Exists) { fileList.Add(FullAcfPath); } WorkShopPath.Refresh(); if (WorkShopAcfPath.Exists) { fileList.Add(WorkShopAcfPath); } } return(fileList); } catch (Exception ex) { Logger.Fatal(ex); return(null); } }
private async void writeStringToFile(string fileName, string content) { //创建新文件,如果该文件存在则自动在末尾追加一个Unique名称。 StorageFile file = await DownloadFolder.CreateFileAsync(fileName, options : CreationCollisionOption.GenerateUniqueName); //把文字写入文件 await FileIO.WriteTextAsync(file, content);; }
public DocumentsController(AccessManager amgr, DownloadFolder downloader, IOptions <Config> options, PrettyTextFile prettifier) { var vfs = amgr.GetReadOnlyFileSystem(); this._outputFiles = new OutputFiles(vfs); this._imageRatio = options.Value.ImageRatio; this._downloader = downloader; this._prettifier = prettifier; }
public List <FileInfo> GetFileList(bool includeDownloads = true, bool includeWorkshop = true) { try { List <FileInfo> FileList = new List <FileInfo>(); if (IsCompressed) { FileList.Add(CompressedArchiveName); } else { CommonFolder.Refresh(); if (CommonFolder.Exists) { FileList.AddRange(GetCommonFiles()); } DownloadFolder.Refresh(); if (includeDownloads && DownloadFolder.Exists) { FileList.AddRange(GetDownloadFiles()); FileList.AddRange(GetPatchFiles()); } WorkShopPath.Refresh(); if (includeWorkshop && WorkShopPath.Exists) { FileList.AddRange(GetWorkshopFiles()); } FullAcfPath.Refresh(); if (FullAcfPath.Exists) { FileList.Add(FullAcfPath); } WorkShopPath.Refresh(); if (WorkShopAcfPath.Exists) { FileList.Add(WorkShopAcfPath); } } return(FileList); } catch (Exception ex) { SLM.RavenClient.Capture(new SharpRaven.Data.SentryEvent(ex)); return(null); } }
private async Task InstallSteamWorkshopItems() { //var currentLib = ""; SteamGame currentSteamGame = null; StoreHandler.Instance.SteamHandler.Games.Where(g => g.Game == GameInfo.Game).Do(s => currentSteamGame = (SteamGame)s); /*SteamHandler.Instance.InstallFolders.Where(f => f.Contains(currentSteamGame.InstallDir)).Do(s => currentLib = s); * * var downloadFolder = Path.Combine(currentLib, "workshop", "downloads", currentSteamGame.AppId.ToString()); * var contentFolder = Path.Combine(currentLib, "workshop", "content", currentSteamGame.AppId.ToString()); */ if (!ModList.Directives.Any(s => s is SteamMeta)) { return; } var result = await Utils.Log(new YesNoIntervention( "The ModList you are installing requires Steam Workshop items to exist. " + "You can check the Workshop Items in the manifest of this ModList. Wabbajack can start Steam for you " + "and download the Items automatically. Do you want to proceed with this step?", "Download Steam Workshop Items?")).Task; if (result != ConfirmationIntervention.Choice.Continue) { return; } await ModList.Directives.OfType <SteamMeta>() .PMap(Queue, async item => { Status("Extracting Steam meta file to temp folder"); var path = DownloadFolder.Combine($"steamWorkshopItem_{item.ItemID}.meta"); if (!path.Exists) { await path.WriteAllBytesAsync(await LoadBytesFromPath(item.SourceDataID)); } Status("Downloading Steam Workshop Item through steam cmd"); var p = new Process { StartInfo = new ProcessStartInfo { FileName = Path.Combine(StoreHandler.Instance.SteamHandler.SteamPath, "steam.exe"), CreateNoWindow = true, Arguments = $"console +workshop_download_item {currentSteamGame.ID} {currentSteamGame.ID}" } }; p.Start(); }); }
public async Task HashArchives() { var hashResults = await DownloadFolder.EnumerateFiles() .Where(e => e.Extension != Consts.HashFileExtension) .PMap(Queue, async e => (await e.FileHashCachedAsync(), e)); HashedArchives.SetTo(hashResults .OrderByDescending(e => e.Item2.LastModified) .GroupBy(e => e.Item1) .Select(e => e.First()) .Select(e => new KeyValuePair <Hash, AbsolutePath>(e.Item1, e.Item2))); }
private void ClientAddWindow_DownloadFolderOpen(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog() { Description = "Select the directory that you want to use as the download location.", SelectedPath = DownloadFolder.Text }; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { DownloadFolder.Text = dlg.SelectedPath; DownloadFolder.Focus(); } }
// TODO: For a better customization/user experience add InArgument<string> DownloadLocation protected override async Task <Action <AsyncCodeActivityContext> > ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken) { PropertyDescriptor dropboxSessionProperty = context.DataContext.GetProperties()[WithDropboxSession.DropboxSessionPropertyName]; IDropboxSession dropboxSession = dropboxSessionProperty?.GetValue(context.DataContext) as IDropboxSession; if (dropboxSession == null) { throw new InvalidOperationException(Resources.DropboxSessionNotFoundException); } await dropboxSession.DownloadFolderAsZipAsync(FolderPath.Get(context), DownloadFolder.Get(context), ZipFileName.Get(context), cancellationToken); return((asyncCodeActivityContext) => { }); }
private async Task InstallIncludedDownloadMetas() { await ModList.Directives .OfType <ArchiveMeta>() .PMap(Queue, async directive => { Status($"Writing included .meta file {directive.To}"); var outPath = DownloadFolder.Combine(directive.To); if (outPath.IsFile) { outPath.Delete(); } await outPath.WriteAllBytesAsync(await LoadBytesFromPath(directive.SourceDataID)); }); }
//去图标网站下载图标 private async Task downloadIconsFromWeb(Album album) { string htmlPage = await htmlDownloadAsync(album.AlbumUrlUserInput); string pattern1 = "srcset=\"[^\"]+"; MatchCollection matches = Regex.Matches(htmlPage, pattern1); string pattern2 = "[a-zA-z]+://[^\\s]*"; //List<string> imageUrls = new List<string>(); foreach (Match match in matches) { MatchCollection matches1 = Regex.Matches(match.Value, pattern2); foreach (Match match_1 in matches1) { if (match_1.Value.Contains("/previews/")) { } else { string[] temp = match_1.Value.Split("/"); string fileName = temp[temp.Length - 1]; string pictureUrl = match_1.Value; album.PictureList.Add( new Picture() { PictureUrl = pictureUrl, PictureFileName = fileName, PicturePageUrl = pictureUrl, } ); } } } album.AlbumName = searchFolderNameInHtml(htmlPage); //判断是否需要为相册创建单独的文件夹 StorageFolder saveFolder = DownloadFolder; if (NeedIndividualFolder) { saveFolder = await DownloadFolder.CreateFolderAsync(album.AlbumName, CreationCollisionOption.GenerateUniqueName); } foreach (Picture picture in album.PictureList) { imageDownload(picture, saveFolder); } }
public async Task<bool> DownloadArchive(Archive archive, bool download, AbsolutePath? destination = null) { try { if (destination == null) destination = DownloadFolder.Combine(archive.Name); await DownloadDispatcher.DownloadWithPossibleUpgrade(archive, destination.Value); } catch (Exception ex) { Utils.Log($"Download error for file {archive.Name}"); Utils.Log(ex.ToString()); return false; } return false; }
private void WriteRemappedFile(RemappedInlineFile directive) { var data = Encoding.UTF8.GetString(LoadBytesFromPath(directive.SourceDataID)); data = data.Replace(Consts.GAME_PATH_MAGIC_BACK, GameFolder); data = data.Replace(Consts.GAME_PATH_MAGIC_DOUBLE_BACK, GameFolder.Replace("\\", "\\\\")); data = data.Replace(Consts.GAME_PATH_MAGIC_FORWARD, GameFolder.Replace("\\", "/")); data = data.Replace(Consts.MO2_PATH_MAGIC_BACK, OutputFolder); data = data.Replace(Consts.MO2_PATH_MAGIC_DOUBLE_BACK, OutputFolder.Replace("\\", "\\\\")); data = data.Replace(Consts.MO2_PATH_MAGIC_FORWARD, OutputFolder.Replace("\\", "/")); data = data.Replace(Consts.DOWNLOAD_PATH_MAGIC_BACK, DownloadFolder); data = data.Replace(Consts.DOWNLOAD_PATH_MAGIC_DOUBLE_BACK, DownloadFolder.Replace("\\", "\\\\")); data = data.Replace(Consts.DOWNLOAD_PATH_MAGIC_FORWARD, DownloadFolder.Replace("\\", "/")); File.WriteAllText(Path.Combine(OutputFolder, directive.To), data); }
public async Task HashArchives() { Utils.Log("Looking for files to hash"); var toHash = DownloadFolder.EnumerateFiles() .Concat(Game.GameLocation().EnumerateFiles()) .ToList(); Utils.Log($"Found {toHash.Count} files to hash"); var hashResults = await toHash .PMap(Queue, UpdateTracker, async e => (await e.FileHashCachedAsync(), e)); HashedArchives.SetTo(hashResults .OrderByDescending(e => e.Item2.LastModified) .GroupBy(e => e.Item1) .Select(e => e.First()) .Select(e => new KeyValuePair <Hash, AbsolutePath>(e.Item1, e.Item2))); }
public async Task <bool> DownloadArchive(Archive archive, bool download, AbsolutePath?destination = null) { try { destination ??= DownloadFolder.Combine(archive.Name); var result = await DownloadDispatcher.DownloadWithPossibleUpgrade(archive, destination.Value); if (result == DownloadDispatcher.DownloadResult.Update) { await destination.Value.MoveToAsync(destination.Value.Parent.Combine(archive.Hash.ToHex())); } } catch (Exception ex) { Utils.Log($"Download error for file {archive.Name}"); Utils.Log(ex.ToString()); return(false); } return(false); }
private void button2_Click(object sender, EventArgs e) { name = comboBox1.Text; FileStream aFile = new FileStream("StuNum.txt", FileMode.Create); StreamWriter sw = new StreamWriter(aFile); sw.WriteLine(textBox1.Text); sw.Close(); aFile = new FileStream("Password.txt", FileMode.Create); sw = new StreamWriter(aFile); sw.WriteLine(textBox2.Text); sw.Close(); StuNumber = textBox1.Text.Trim(); if (button2.Text == "激活离线练习") { if (MessageBox.Show("没有找到题库,是否帮助您下载一份?(需要联网)", "", MessageBoxButtons.YesNo) == DialogResult.Yes) { button2.Text = "正在下载"; DownloadFolder.downftp("ftp://202.118.26.80", "ChoiceSource", Directory.GetCurrentDirectory()); button2.Text = "离线练习"; MessageBox.Show("传输完毕"); } else { if (Directory.Exists("ChoiceSource")) { button2.Text = "离线练习"; } } } else { StuNumber = textBox1.Text; base.DialogResult = DialogResult.No; } }
public async void DeleteFilesAsync() { try { if (SteamAppsFolder.Exists) { await Task.Run(() => SteamAppsFolder.Delete(true)); } if (WorkshopFolder.Exists) { await Task.Run(() => WorkshopFolder.Delete(true)); } if (DownloadFolder.Exists) { await Task.Run(() => DownloadFolder.Delete(true)); } } catch (Exception ex) { logger.Fatal(ex); } }
protected override async Task <bool> _Begin(CancellationToken cancel) { if (cancel.IsCancellationRequested) { return(false); } var metric = Metrics.Send(Metrics.BeginInstall, ModList.Name); Utils.Log("Configuring Processor"); Queue.SetActiveThreadsObservable(ConstructDynamicNumThreads(await RecommendQueueSize())); if (GameFolder == null) { GameFolder = Game.TryGetGameLocation(); } if (GameFolder == null) { var otherGame = Game.CommonlyConfusedWith.Where(g => g.MetaData().IsInstalled).Select(g => g.MetaData()).FirstOrDefault(); if (otherGame != null) { await Utils.Log(new CriticalFailureIntervention( $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed, we did however find a installed " + $"copy of {otherGame.HumanFriendlyGameName}, did you install the wrong game?", $"Could not locate {Game.HumanFriendlyGameName}")) .Task; } else { await Utils.Log(new CriticalFailureIntervention( $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed", $"Could not locate {Game.HumanFriendlyGameName}")) .Task; } Utils.Log("Exiting because we couldn't find the game folder."); return(false); } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Validating Game ESMs"); ValidateGameESMs(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Validating Modlist"); await ValidateModlist.RunValidation(ModList); OutputFolder.CreateDirectory(); DownloadFolder.CreateDirectory(); if (OutputFolder.Combine(Consts.MO2ModFolderName).IsDirectory&& WarnOnOverwrite) { if ((await Utils.Log(new ConfirmUpdateOfExistingInstall { ModListName = ModList.Name, OutputFolder = OutputFolder }).Task) == ConfirmUpdateOfExistingInstall.Choice.Abort) { Utils.Log("Exiting installation at the request of the user, existing mods folder found."); return(false); } } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Optimizing ModList"); await OptimizeModlist(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Hashing Archives"); await HashArchives(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Downloading Missing Archives"); await DownloadArchives(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Hashing Remaining Archives"); await HashArchives(); var missing = ModList.Archives.Where(a => !HashedArchives.ContainsKey(a.Hash)).ToList(); if (missing.Count > 0) { foreach (var a in missing) { Info($"Unable to download {a.Name}"); } if (IgnoreMissingFiles) { Info("Missing some archives, but continuing anyways at the request of the user"); } else { Error("Cannot continue, was unable to download one or more archives"); } } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Priming VFS"); await PrimeVFS(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Building Folder Structure"); BuildFolderStructure(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Archives"); await InstallArchives(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Included files"); await InstallIncludedFiles(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Archive Metas"); await InstallIncludedDownloadMetas(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Building BSAs"); await BuildBSAs(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Generating Merges"); await zEditIntegration.GenerateMerges(this); UpdateTracker.NextStep("Set MO2 into portable"); await ForcePortable(); UpdateTracker.NextStep("Create Empty Output Mods"); CreateOutputMods(); UpdateTracker.NextStep("Updating System-specific ini settings"); SetScreenSizeInPrefs(); UpdateTracker.NextStep("Installation complete! You may exit the program."); var metric2 = Metrics.Send(Metrics.FinishInstall, ModList.Name); return(true); }
public List <FileInfo> GetDownloadFiles() => DownloadFolder.EnumerateFiles("*", SearchOption.AllDirectories).ToList();
public async Task <bool> DeleteFilesAsync(List.TaskInfo CurrentTask = null) { try { if (IsCompressed) { CompressedArchiveName.Refresh(); if (CompressedArchiveName.Exists) { await Task.Run(() => CompressedArchiveName.Delete()); } } else { List <FileInfo> FileList = GetFileList(); if (FileList.Count > 0) { Parallel.ForEach(FileList, currentFile => { try { CurrentTask?.mre.WaitOne(); currentFile.Refresh(); if (currentFile.Exists) { if (CurrentTask != null) { CurrentTask.mre.WaitOne(); CurrentTask.TaskStatusInfo = $"Deleting: {currentFile.Name} ({Functions.FileSystem.FormatBytes(currentFile.Length)})"; Main.FormAccessor.TaskManager_Logs.Add($"[{DateTime.Now}] [{CurrentTask.SteamApp.AppName}] Deleting file: {currentFile.FullName}"); } File.SetAttributes(currentFile.FullName, FileAttributes.Normal); currentFile.Delete(); } } catch (Exception ex) { logger.Fatal(ex); } } ); } CommonFolder.Refresh(); // common folder, if exists if (CommonFolder.Exists) { await Task.Run(() => CommonFolder.Delete(true)); } DownloadFolder.Refresh(); // downloading folder, if exists if (DownloadFolder.Exists) { await Task.Run(() => DownloadFolder.Delete(true)); } WorkShopPath.Refresh(); // workshop folder, if exists if (WorkShopPath.Exists) { await Task.Run(() => WorkShopPath.Delete(true)); } FullAcfPath.Refresh(); // game .acf file if (FullAcfPath.Exists) { File.SetAttributes(FullAcfPath.FullName, FileAttributes.Normal); FullAcfPath.Delete(); } WorkShopAcfPath.Refresh(); // workshop .acf file if (WorkShopAcfPath.Exists) { File.SetAttributes(WorkShopAcfPath.FullName, FileAttributes.Normal); WorkShopAcfPath.Delete(); } if (CurrentTask != null) { CurrentTask.TaskStatusInfo = ""; } } return(true); } catch (FileNotFoundException ex) { logger.Error(ex); return(true); } catch (DirectoryNotFoundException ex) { logger.Error(ex); return(true); } catch (IOException ex) { logger.Error(ex); return(true); } catch (UnauthorizedAccessException ex) { logger.Error(ex); return(true); } catch (Exception ex) { MessageBox.Show(ex.ToString()); logger.Fatal(ex); await SLM.RavenClient.CaptureAsync(new SharpRaven.Data.SentryEvent(ex)); return(false); } }
public List <FileInfo> GetFileList(bool includeDownloads = true, bool includeWorkshop = true) { try { var FileList = new List <FileInfo>(); if (IsCompressed) { FileList.Add(CompressedArchiveName); } else { CommonFolder.Refresh(); if (CommonFolder.Exists) { var commonFiles = GetCommonFiles(); if (commonFiles != null) { FileList.AddRange(commonFiles); } } DownloadFolder.Refresh(); if (includeDownloads && DownloadFolder.Exists) { var downloadFiles = GetDownloadFiles(); var patchFiles = GetPatchFiles(); if (downloadFiles != null) { FileList.AddRange(downloadFiles); } if (patchFiles != null) { FileList.AddRange(patchFiles); } } WorkShopPath.Refresh(); if (includeWorkshop && WorkShopPath.Exists) { var workshopPath = GetWorkshopFiles(); FileList.AddRange(workshopPath); } FullAcfPath.Refresh(); if (FullAcfPath.Exists) { FileList.Add(FullAcfPath); } WorkShopPath.Refresh(); if (WorkShopAcfPath.Exists) { FileList.Add(WorkShopAcfPath); } } return(FileList); } catch (Exception ex) { Logger.Fatal(ex); return(null); } }
private void ClientAddWindow_DownloadFolderClear(object sender, RoutedEventArgs e) { DownloadFolder.Text = ""; DownloadFolder.Focus(); }
public DownloadFolder(DownloadFolder downloadFolder) { FullyLoaded = downloadFolder.FullyLoaded; Date_Updated = downloadFolder.Date_Updated; Parent_Folder = new Folder(downloadFolder.Parent_Folder); }
/// <summary> /// The user may already have some files in the OutputFolder. If so we can go through these and /// figure out which need to be updated, deleted, or left alone /// </summary> public async Task OptimizeModlist() { Utils.Log("Optimizing ModList directives"); // Clone the ModList so our changes don't modify the original data ModList = ModList.Clone(); var indexed = ModList.Directives.ToDictionary(d => d.To); var profileFolder = OutputFolder.Combine("profiles"); var savePath = (RelativePath)"saves"; UpdateTracker.NextStep("Looking for files to delete"); await OutputFolder.EnumerateFiles() .PMap(Queue, UpdateTracker, async f => { var relativeTo = f.RelativeTo(OutputFolder); if (indexed.ContainsKey(relativeTo) || f.InFolder(DownloadFolder)) { return; } if (f.InFolder(profileFolder) && f.Parent.FileName == savePath) { return; } Utils.Log($"Deleting {relativeTo} it's not part of this ModList"); await f.DeleteAsync(); }); Utils.Log("Cleaning empty folders"); var expectedFolders = indexed.Keys .Select(f => f.RelativeTo(OutputFolder)) // We ignore the last part of the path, so we need a dummy file name .Append(DownloadFolder.Combine("_")) .Where(f => f.InFolder(OutputFolder)) .SelectMany(path => { // Get all the folders and all the folder parents // so for foo\bar\baz\qux.txt this emits ["foo", "foo\\bar", "foo\\bar\\baz"] var split = ((string)path.RelativeTo(OutputFolder)).Split('\\'); return(Enumerable.Range(1, split.Length - 1).Select(t => string.Join("\\", split.Take(t)))); }) .Distinct() .Select(p => OutputFolder.Combine(p)) .ToHashSet(); try { var toDelete = OutputFolder.EnumerateDirectories(true) .Where(p => !expectedFolders.Contains(p)) .OrderByDescending(p => ((string)p).Length) .ToList(); foreach (var dir in toDelete) { await dir.DeleteDirectory(dontDeleteIfNotEmpty : true); } } catch (Exception) { // ignored because it's not worth throwing a fit over Utils.Log("Error when trying to clean empty folders. This doesn't really matter."); } var existingfiles = OutputFolder.EnumerateFiles().ToHashSet(); UpdateTracker.NextStep("Looking for unmodified files"); (await indexed.Values.PMap(Queue, UpdateTracker, async d => { // Bit backwards, but we want to return null for // all files we *want* installed. We return the files // to remove from the install list. var path = OutputFolder.Combine(d.To); if (!existingfiles.Contains(path)) { return(null); } return(await path.FileHashCachedAsync() == d.Hash ? d : null); })) .Do(d => { if (d != null) { indexed.Remove(d.To); } }); UpdateTracker.NextStep("Updating ModList"); Utils.Log($"Optimized {ModList.Directives.Count} directives to {indexed.Count} required"); var requiredArchives = indexed.Values.OfType <FromArchive>() .GroupBy(d => d.ArchiveHashPath.BaseHash) .Select(d => d.Key) .ToHashSet(); ModList.Archives = ModList.Archives.Where(a => requiredArchives.Contains(a.Hash)).ToList(); ModList.Directives = indexed.Values.ToList(); }
public async Task <bool> DeleteFilesAsync(List.TaskInfo CurrentTask = null) { try { if (IsCompressed) { CompressedArchiveName.Refresh(); if (CompressedArchiveName.Exists) { await Task.Run(() => CompressedArchiveName.Delete()); } } else { List <FileInfo> FileList = GetFileList(); if (FileList.Count > 0) { Parallel.ForEach(FileList, currentFile => { try { CurrentTask?.mre.WaitOne(); currentFile.Refresh(); if (currentFile.Exists) { if (CurrentTask != null) { CurrentTask.mre.WaitOne(); CurrentTask.TaskStatusInfo = Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.TaskStatus_DeletingFile)), new { FileName = currentFile.Name, FormattedFileSize = Functions.FileSystem.FormatBytes(currentFile.Length) }); if (CurrentTask.ReportFileMovement) { Main.FormAccessor.TaskManager_Logs.Report($"[{DateTime.Now}] [{AppName}] {Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.TaskStatus_DeletingFile)), new { FileName = currentFile.Name, FormattedFileSize = Functions.FileSystem.FormatBytes(currentFile.Length) })}"); } } File.SetAttributes(currentFile.FullName, FileAttributes.Normal); currentFile.Delete(); } } catch (Exception ex) { Logger.Fatal(ex); } } ); } CommonFolder.Refresh(); // common folder, if exists if (CommonFolder.Exists) { await Task.Run(() => CommonFolder.Delete(true)); } DownloadFolder.Refresh(); // downloading folder, if exists if (DownloadFolder.Exists) { await Task.Run(() => DownloadFolder.Delete(true)); } WorkShopPath.Refresh(); // workshop folder, if exists if (WorkShopPath.Exists) { await Task.Run(() => WorkShopPath.Delete(true)); } FullAcfPath.Refresh(); // game .acf file if (FullAcfPath.Exists) { File.SetAttributes(FullAcfPath.FullName, FileAttributes.Normal); FullAcfPath.Delete(); } WorkShopAcfPath.Refresh(); // workshop .acf file if (WorkShopAcfPath.Exists) { File.SetAttributes(WorkShopAcfPath.FullName, FileAttributes.Normal); WorkShopAcfPath.Delete(); } if (CurrentTask != null) { CurrentTask.TaskStatusInfo = ""; } } return(true); } catch (FileNotFoundException ex) { Logger.Error(ex); return(true); } catch (DirectoryNotFoundException ex) { Logger.Error(ex); return(true); } catch (IOException ex) { Logger.Error(ex); return(true); } catch (UnauthorizedAccessException ex) { Logger.Error(ex); return(true); } catch (Exception ex) { MessageBox.Show(ex.ToString()); Logger.Fatal(ex); return(false); } }
private IEnumerable <FileInfo> GetDownloadFiles() => DownloadFolder.EnumerateFiles("*", SearchOption.AllDirectories);
protected override async Task <bool> _Begin(CancellationToken cancel) { if (cancel.IsCancellationRequested) { return(false); } await Metrics.Send(Metrics.BeginInstall, ModList.Name); Utils.Log("Configuring Processor"); FileExtractor2.FavorPerfOverRAM = FavorPerfOverRam; if (GameFolder == null) { GameFolder = Game.TryGetGameLocation(); } if (GameFolder == null) { var otherGame = Game.CommonlyConfusedWith.Where(g => g.MetaData().IsInstalled).Select(g => g.MetaData()).FirstOrDefault(); if (otherGame != null) { await Utils.Log(new CriticalFailureIntervention( $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed, we did however find a installed " + $"copy of {otherGame.HumanFriendlyGameName}, did you install the wrong game?", $"Could not locate {Game.HumanFriendlyGameName}")) .Task; } else { await Utils.Log(new CriticalFailureIntervention( $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed", $"Could not locate {Game.HumanFriendlyGameName}")) .Task; } Utils.Log("Exiting because we couldn't find the game folder."); return(false); } Utils.Log($"Install Folder: {OutputFolder}"); Utils.Log($"Downloads Folder: {DownloadFolder}"); Utils.Log($"Game Folder: {GameFolder.Value}"); Utils.Log($"Wabbajack Folder: {AbsolutePath.EntryPoint}"); var watcher = new DiskSpaceWatcher(cancel, new[] { OutputFolder, DownloadFolder, GameFolder.Value, AbsolutePath.EntryPoint }, (long)2 << 31, drive => { Utils.Log($"Aborting due to low space on {drive.Name}"); Abort(); }); var watcherTask = watcher.Start(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Validating Game ESMs"); await ValidateGameESMs(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Creating Output Folders"); OutputFolder.CreateDirectory(); DownloadFolder.CreateDirectory(); if (OutputFolder.Combine(Consts.MO2ModFolderName).IsDirectory&& WarnOnOverwrite) { if ((await Utils.Log(new ConfirmUpdateOfExistingInstall { ModListName = ModList.Name, OutputFolder = OutputFolder }).Task) == ConfirmUpdateOfExistingInstall.Choice.Abort) { Utils.Log("Exiting installation at the request of the user, existing mods folder found."); return(false); } } // Reduce to one thread if downloads on HDD, else use specified. Hashing on HDD has no benefit with more threads. if (new PhysicalDisk(DownloadFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads) { DesiredThreads.OnNext(1); } else { DesiredThreads.OnNext(DiskThreads); } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Optimizing ModList"); await OptimizeModlist(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Hashing Archives"); await HashArchives(); // Set to download thread count. DesiredThreads.OnNext(DownloadThreads); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Downloading Missing Archives"); await DownloadArchives(); // Reduce to one thread if downloads on HDD, else use specified. Hashing on HDD has no benefit with more threads. if (new PhysicalDisk(DownloadFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads) { DesiredThreads.OnNext(1); } else { DesiredThreads.OnNext(DiskThreads); } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Hashing Remaining Archives"); await HashArchives(); var missing = ModList.Archives.Where(a => !HashedArchives.ContainsKey(a.Hash)).ToList(); if (missing.Count > 0) { foreach (var a in missing) { Info($"Unable to download {a.Name} ({a.State.PrimaryKeyString})"); } if (IgnoreMissingFiles) { Info("Missing some archives, but continuing anyways at the request of the user"); } else { Error("Cannot continue, was unable to download one or more archives"); } } // Reduce to two threads if output on HDD, else use specified. Installing files seems to have a slight benefit with two threads. if (new PhysicalDisk(OutputFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads) { DesiredThreads.OnNext(2); } else { DesiredThreads.OnNext(DiskThreads); } if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Extracting Modlist contents"); await ExtractModlist(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Priming VFS"); await PrimeVFS(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Building Folder Structure"); BuildFolderStructure(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Archives"); await InstallArchives(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Included files"); await InstallIncludedFiles(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Installing Archive Metas"); await InstallIncludedDownloadMetas(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Building BSAs"); await BuildBSAs(); if (cancel.IsCancellationRequested) { return(false); } UpdateTracker.NextStep("Generating Merges"); await zEditIntegration.GenerateMerges(this); UpdateTracker.NextStep("Set MO2 into portable"); await ForcePortable(); UpdateTracker.NextStep("Create Empty Output Mods"); CreateOutputMods(); UpdateTracker.NextStep("Updating System-specific ini settings"); SetScreenSizeInPrefs(); UpdateTracker.NextStep("Compacting files"); await CompactFiles(); UpdateTracker.NextStep("Installation complete! You may exit the program."); await ExtractedModlistFolder !.DisposeAsync(); await Metrics.Send(Metrics.FinishInstall, ModList.Name); return(true); }