private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { Program.Closing = true; if ((Program.webClient != null) && Program.webClient.IsBusy) { Program.webClient.CancelAsync(); } if (OperationHandler.CurrentOperation != OperationHandler.Operations.NONE) { Thread.Sleep(1000); } TempFileCache.ClearCache(); Program.OperationError(); if (OperationHandler.CurrentOperation <= OperationHandler.Operations.INSTALLER_UPDATE) { return; } // Sanatize Operation MessageBox.Show((OperationHandler.CurrentOperationName + " was Cancelled!"), BuildInfo.Name, MessageBoxButtons.OK, MessageBoxIcon.Error); }
internal static void LogError(string msg) { TempFileCache.ClearCache(); OperationError(); try { string filePath = Directory.GetCurrentDirectory() + $@"\MLInstaller_{DateTime.Now:yy-M-dd_HH-mm-ss.fff}.log"; File.WriteAllText(filePath, msg); if (Config.HighlightLogFileLocation) { Process.Start("explorer.exe", $"/select, {filePath}"); } #if DEBUG FinishingMessageBox(msg, MessageBoxButtons.OK, MessageBoxIcon.Error); #else FinishingMessageBox($"INTERNAL FAILURE! Please upload the log file \"{filePath}\" when requesting support.", MessageBoxButtons.OK, MessageBoxIcon.Error); #endif } catch (UnauthorizedAccessException) { FinishingMessageBox($"Couldn't create log file! Try running the Installer as Administrator or run the Installer from a different directory.", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
internal static void Automated_Install(string destination, string selected_version, bool is_x86, bool legacy_version) { Program.SetCurrentOperation("Downloading MelonLoader..."); string downloadurl = Config.Download_MelonLoader + "/" + selected_version + "/MelonLoader." + ((!legacy_version && is_x86) ? "x86" : "x64") + ".zip"; string temp_path = TempFileCache.CreateFile(); try { Program.webClient.DownloadFileAsync(new Uri(downloadurl), temp_path); while (Program.webClient.IsBusy) { } } catch (Exception ex) { Program.LogError(ex.ToString()); return; } Program.SetTotalPercentage(50); if (Program.Closing) { return; } string repo_hash_url = Config.Download_MelonLoader + "/" + selected_version + "/MelonLoader." + ((!legacy_version && is_x86) ? "x86" : "x64") + ".sha512"; string repo_hash = null; try { repo_hash = Program.webClient.DownloadString(repo_hash_url); } catch { repo_hash = null; } if (string.IsNullOrEmpty(repo_hash)) { Program.LogError("Failed to get SHA512 Hash from Repo!"); return; } if (Program.Closing) { return; } SHA512Managed sha512 = new SHA512Managed(); byte[] checksum = sha512.ComputeHash(File.ReadAllBytes(temp_path)); if ((checksum == null) || (checksum.Length <= 0)) { Program.LogError("Failed to get SHA512 Hash from Temp File!"); return; } string file_hash = BitConverter.ToString(checksum).Replace("-", string.Empty); if (string.IsNullOrEmpty(file_hash)) { Program.LogError("Failed to get SHA512 Hash from Temp File!"); return; } if (!file_hash.Equals(repo_hash)) { Program.LogError("SHA512 Hash from Temp File does not match Repo Hash!"); return; } Program.SetCurrentOperation("Extracting MelonLoader..."); try { string MelonLoader_Folder = Path.Combine(destination, "MelonLoader"); if (Directory.Exists(MelonLoader_Folder)) { ThreadHandler.RecursiveFuncRun(delegate(ThreadHandler.RecursiveFuncRecurse recurse) { try { Directory.Delete(MelonLoader_Folder, true); } catch (Exception ex) { if (!ex.GetType().IsAssignableFrom(typeof(UnauthorizedAccessException)) && !ex.GetType().IsAssignableFrom(typeof(IOException))) { throw ex; } DialogResult result = MessageBox.Show($"Unable to remove Existing MelonLoader Folder! Make sure the Unity Game is not running or try running the Installer as Administrator.", BuildInfo.Name, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (result == DialogResult.Retry) { recurse.Invoke(); } else { throw ex; } } }); } string proxy_path = null; if (GetExistingProxyPath(destination, out proxy_path)) { ThreadHandler.RecursiveFuncRun(delegate(ThreadHandler.RecursiveFuncRecurse recurse) { try { File.Delete(proxy_path); } catch (Exception ex) { if (!ex.GetType().IsAssignableFrom(typeof(UnauthorizedAccessException)) && !ex.GetType().IsAssignableFrom(typeof(IOException))) { throw ex; } DialogResult result = MessageBox.Show($"Unable to remove Existing Proxy Module! Make sure the Unity Game is not running or try running the Installer as Administrator.", BuildInfo.Name, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (result == DialogResult.Retry) { recurse.Invoke(); } else { throw ex; } } }); } using FileStream stream = new FileStream(temp_path, FileMode.Open, FileAccess.Read); using ZipArchive zip = new ZipArchive(stream); int total_entry_count = zip.Entries.Count; for (int i = 0; i < total_entry_count; i++) { if (Program.Closing) { break; } int percentage = ((i / total_entry_count) * 100); Program.SetCurrentPercentage(percentage); Program.SetTotalPercentage((50 + (percentage / 2))); ZipArchiveEntry entry = zip.Entries[i]; string fullPath = Path.Combine(destination, entry.FullName); if (!fullPath.StartsWith(destination)) { throw new IOException("Extracting Zip entry would have resulted in a file outside the specified destination directory."); } string filename = Path.GetFileName(fullPath); if (filename.Length != 0) { if (!legacy_version && filename.Equals("version.dll")) { foreach (string proxyname in ProxyNames) { string new_proxy_path = Path.Combine(destination, (proxyname + ".dll")); if (File.Exists(new_proxy_path)) { continue; } fullPath = new_proxy_path; break; } } string directorypath = Path.GetDirectoryName(fullPath); if (!Directory.Exists(directorypath)) { Directory.CreateDirectory(directorypath); } using FileStream targetStream = new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.Write); using Stream entryStream = entry.Open(); ThreadHandler.RecursiveFuncRun(delegate(ThreadHandler.RecursiveFuncRecurse recurse) { try { entryStream.CopyTo(targetStream); } catch (Exception ex) { if (!ex.GetType().IsAssignableFrom(typeof(UnauthorizedAccessException)) && !ex.GetType().IsAssignableFrom(typeof(IOException))) { throw ex; } DialogResult result = MessageBox.Show($"Couldn't extract file {filename}! Make sure the Unity Game is not running or try running the Installer as Administrator.", BuildInfo.Name, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (result == DialogResult.Retry) { recurse.Invoke(); } else { throw ex; } } }); continue; } if (entry.Length != 0) { throw new IOException("Zip entry name ends in directory separator character but contains data."); } if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); } } ThreadHandler.RecursiveFuncRun(delegate(ThreadHandler.RecursiveFuncRecurse recurse) { try { DowngradeMelonPreferences(destination, legacy_version); } catch (Exception ex) { if (!ex.GetType().IsAssignableFrom(typeof(UnauthorizedAccessException)) && !ex.GetType().IsAssignableFrom(typeof(IOException))) { throw ex; } DialogResult result = MessageBox.Show($"Unable to Downgrade MelonLoader Preferences! Make sure the Unity Game is not running or try running the Installer as Administrator.", BuildInfo.Name, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (result == DialogResult.Retry) { recurse.Invoke(); } else { throw ex; } } }); ExtraDirectoryChecks(destination); ThreadHandler.RecursiveFuncRun(delegate(ThreadHandler.RecursiveFuncRecurse recurse) { try { ExtraCleanupCheck(destination); } catch (Exception ex) { if (!ex.GetType().IsAssignableFrom(typeof(UnauthorizedAccessException)) && !ex.GetType().IsAssignableFrom(typeof(IOException))) { throw ex; } DialogResult result = MessageBox.Show($"Couldn't do Extra File Cleanup! Make sure the Unity Game is not running or try running the Installer as Administrator.", BuildInfo.Name, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (result == DialogResult.Retry) { recurse.Invoke(); } else { throw ex; } } }); } catch (Exception ex) { Program.LogError(ex.ToString()); return; } if (Program.Closing) { return; } TempFileCache.ClearCache(); Program.OperationSuccess(); Program.FinishingMessageBox((CurrentOperationName + " was Successful!"), MessageBoxButtons.OK, MessageBoxIcon.None); }
internal static void CheckForInstallerUpdate() { Program.webClient.Headers.Clear(); Program.webClient.Headers.Add("User-Agent", "request"); string response = null; try { response = Program.webClient.DownloadString(Config.Repo_API_Installer); } catch { response = null; } if (string.IsNullOrEmpty(response)) { GetReleases(); return; } if (Program.Closing) { return; } JsonArray data = JsonValue.Parse(response).AsJsonArray; if (data.Count <= 0) { GetReleases(); return; } JsonValue release = data[0]; JsonArray assets = release["assets"].AsJsonArray; if (assets.Count <= 0) { GetReleases(); return; } string version = release["tag_name"].AsString; if (version.Equals(BuildInfo.Version)) { GetReleases(); return; } Program.mainForm.Invoke(new Action(() => { Program.mainForm.InstallerUpdateNotice.Visible = true; })); if (!Program.RunInstallerUpdateCheck || !Config.AutoUpdateInstaller) { GetReleases(); return; } OperationHandler.CurrentOperation = OperationHandler.Operations.INSTALLER_UPDATE; Program.mainForm.Invoke(new Action(() => { Program.mainForm.Tab_Output.Text = "UPDATE "; Program.SetCurrentOperation("Updating Installer..."); Program.mainForm.PageManager.Controls.Clear(); Program.mainForm.PageManager.Controls.Add(Program.mainForm.Tab_Output); })); string downloadurl = assets[0]["browser_download_url"].AsString; string temp_path = TempFileCache.CreateFile(); try { Program.webClient.DownloadFileAsync(new Uri(downloadurl), temp_path); while (Program.webClient.IsBusy) { } } catch (Exception ex) { TempFileCache.ClearCache(); Program.LogError(ex.ToString()); RefreshReleases(); return; } Program.SetTotalPercentage(50); if (Program.Closing) { return; } string repo_hash = null; try { repo_hash = Program.webClient.DownloadString(assets[1]["browser_download_url"].AsString); } catch { repo_hash = null; } if (string.IsNullOrEmpty(repo_hash)) { TempFileCache.ClearCache(); Program.LogError("Failed to get SHA512 Hash from Repo!"); RefreshReleases(); return; } if (Program.Closing) { return; } SHA512Managed sha512 = new SHA512Managed(); byte[] checksum = sha512.ComputeHash(File.ReadAllBytes(temp_path)); if ((checksum == null) || (checksum.Length <= 0)) { TempFileCache.ClearCache(); Program.LogError("Failed to get SHA512 Hash from Temp File!"); RefreshReleases(); return; } string file_hash = BitConverter.ToString(checksum).Replace("-", string.Empty); if (string.IsNullOrEmpty(file_hash) || !file_hash.Equals(repo_hash)) { TempFileCache.ClearCache(); Program.LogError("Failed to get SHA512 Hash from Temp File!"); RefreshReleases(); return; } Program.OperationSuccess(); string exe_path = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); string tmp_file_path = Path.Combine(exe_path, (Path.GetFileNameWithoutExtension(downloadurl) + ".tmp.exe")); if (File.Exists(tmp_file_path)) { File.Delete(tmp_file_path); } File.Move(temp_path, tmp_file_path); Process.Start(tmp_file_path); Process.GetCurrentProcess().Kill(); }