/// <summary> /// Attempts to apply the ASI. If the ASI is already up to date, false is returned. /// </summary> /// <param name="asi">ASI to apply or update</param> /// <param name="operationCompletedCallback">Callback when operation is done</param> /// <returns></returns> internal bool ApplyASI(ASIMod asi, Action operationCompletedCallback) { Log.Information($@"Installing {asi.Name} v{asi.Version} to target {SelectedTarget.TargetPath}"); //Check if this is actually installed or not (or outdated) var installedInfo = asi.InstalledInfo; if (installedInfo != null) { var correspondingAsi = getManifestModByHash(installedInfo.Hash); if (correspondingAsi != asi) { //Outdated - update mod InstallASI(asi, installedInfo, operationCompletedCallback); } else { Log.Information(@"The installed version of this ASI is already up to date."); return(false); } } else { InstallASI(asi, operationCompletedCallback: operationCompletedCallback); } return(true); }
internal void DeleteASI(ASIMod asi) { var installedInfo = asi.InstalledInfo; if (installedInfo != null) { //Up to date - delete mod Log.Information(@"Deleting installed ASI: " + installedInfo.InstalledPath); File.Delete(installedInfo.InstalledPath); RefreshASIStates(); } }
private ASIModUpdateGroup getUpdateGroupByMod(ASIMod mod) { foreach (var updateGroup in ASIModUpdateGroups) { var asi = updateGroup.ASIModVersions.FirstOrDefault(x => x == mod); if (asi != null) { return(updateGroup); } } return(null); }
internal void DeleteASI(ASIMod asi, Action <Exception> exceptionCallback = null) { var installedInfo = asi.InstalledInfo; if (installedInfo != null) { //Up to date - delete mod Log.Information(@"Deleting installed ASI: " + installedInfo.InstalledPath); try { File.Delete(installedInfo.InstalledPath); RefreshASIStates(); } catch (Exception e) { Log.Error($@"Error deleting asi: {e.Message}"); exceptionCallback?.Invoke(e); } } }
private void InstallASI(ASIMod asiToInstall, InstalledASIMod oldASIToRemoveOnSuccess = null, Action operationCompletedCallback = null) { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (a, b) => { ASIModUpdateGroup g = getUpdateGroupByMod(asiToInstall); string destinationFilename = $@"{asiToInstall.InstalledPrefix}-v{asiToInstall.Version}.asi"; string cachedPath = Path.Combine(CachedASIsFolder, destinationFilename); string destinationDirectory = MEDirectories.ASIPath(SelectedTarget); string finalPath = Path.Combine(destinationDirectory, destinationFilename); string md5; if (File.Exists(cachedPath)) { //Check hash first md5 = BitConverter.ToString(System.Security.Cryptography.MD5.Create().ComputeHash(File.ReadAllBytes(cachedPath))).Replace(@"-", "").ToLower(); if (md5 == asiToInstall.Hash) { Log.Information($@"Copying local ASI from libary to destination: {cachedPath} -> {finalPath}"); File.Copy(cachedPath, finalPath); operationCompletedCallback?.Invoke(); return; } } WebRequest request = WebRequest.Create(asiToInstall.DownloadLink); Log.Information(@"Fetching remote ASI from server"); using WebResponse response = request.GetResponse(); MemoryStream memoryStream = new MemoryStream(); response.GetResponseStream().CopyTo(memoryStream); //MD5 check on file for security md5 = BitConverter.ToString(System.Security.Cryptography.MD5.Create().ComputeHash(memoryStream.ToArray())).Replace(@"-", "").ToLower(); if (md5 != asiToInstall.Hash) { //ERROR! Log.Error(@"Downloaded ASI did not match the manifest! It has the wrong hash."); } else { Log.Information(@"Fetched remote ASI from server. Installing ASI to " + finalPath); File.WriteAllBytes(finalPath, memoryStream.ToArray()); if (!Directory.Exists(CachedASIsFolder)) { Directory.CreateDirectory(CachedASIsFolder); } Log.Information(@"Caching ASI to local ASI library: " + cachedPath); File.WriteAllBytes(cachedPath, memoryStream.ToArray()); //cache it if (oldASIToRemoveOnSuccess != null) { File.Delete(oldASIToRemoveOnSuccess.InstalledPath); } }; }; worker.RunWorkerCompleted += (a, b) => { RefreshASIStates(); operationCompletedCallback?.Invoke(); }; worker.RunWorkerAsync(); }