static void Main(string[] args) { Helper.GetInputOptions(args); DisableUMCallbackFilter(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (args.Length == 0) { MessageBox.Show("Bạn phải cung cấp tên profile vào đối số cho Launcher này!", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } CurrentVersion = Application.ProductVersion; AppDomain.CurrentDomain.AssemblyResolve += ResolveEventHandler; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Unhandled); RootDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (Settings.InputOptions?.LogPath == null) { log = StreamWriter.Null; // use a blackhole as log file } else { log = new StreamWriter(File.Open(Path.Combine(RootDirectory, Settings.InputOptions.LogPath), FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8); } PackageDirectory = Path.Combine(RootDirectory, "Pkg"); ProfileDirectory = Path.Combine(RootDirectory, "Prfl"); DateTime now = DateTime.Now; log.Log(now.ToString("F", new CultureInfo("en-US"))); log.Log("Dotnet Runtime Patcher by Meigyoku Thmn"); log.Log($"Version {CurrentVersion}"); var DebugBuild = Settings.InputOptions.Debug; var pd = new ProgressDialog(IntPtr.Zero); pd.Title = "Đang tải dữ liệu"; pd.Maximum = 100; pd.Value = 0; pd.Line1 = "Thiết đặt CSScript"; pd.Line2 = "Xin vui lòng chờ trong giây lát..."; pd.Line3 = " "; pd.ShowDialog(ProgressDialog.PROGDLG.Modal, ProgressDialog.PROGDLG.NoMinimize); Thread.Sleep(5000); var options = new Options(RootDirectory, "Options.jsonc"); options.Save(); log.Log("Set up CSScript."); CSScript.GlobalSettings.UseAlternativeCompiler = CodeDom_Roslyn.LocateRoslynCSSProvider(); CSScript.GlobalSettings.RoslynDir = CodeDom_Roslyn.LocateRoslynCompilers(); CSScript.EvaluatorConfig.DebugBuild = DebugBuild; log.Log($"Read {Path.Combine(ProfileDirectory, args[0] + ".jsonc")}"); var exeCfg = JObject.Parse(File.ReadAllText(Path.Combine(ProfileDirectory, args[0] + ".jsonc"))); var targetPath = (string)exeCfg["targetPath"]; if (targetPath == null) { log.Log($"Target path doesn't exist in profile!"); MessageBox.Show("Đường dẫn đến 'file thực thi' không tồn tại trong thiết lập!"); return; } TargetDirectory = Path.GetDirectoryName(targetPath); var package = (string)exeCfg["package"]; if (package == null) { log.Log($"Package name in profile is missing!"); MessageBox.Show("Không hề có thiết lập gói!"); return; } log.Log($"Read {Path.Combine(PackageDirectory, package, "versions.jsonc")}"); var versionsCfg = JObject.Parse(File.ReadAllText(Path.Combine(PackageDirectory, package, "versions.jsonc"))); var targetInfo = GetChecksumAndSize(targetPath); var version = versionsCfg[targetInfo.Hash]; if (version == null || (uint)version["size"] != targetInfo.Size) { log.Log("Unable to find suitable patch for target executable file."); MessageBox.Show("Không tìm thấy bản patch phù hợp, có thể phần mềm của bạn đang là phiên bản khác rồi!"); return; } TargetVersion = (string)version["ver"]; if (TargetVersion == null) { log.Log("TargetVersion is null"); } var patchName = (string)version["name"]; if (patchName == null) { log.Log("patchName is null"); } TargetIcon = Icon.ExtractAssociatedIcon(targetPath); TargetAssembly = Assembly.LoadFrom(targetPath); var referenceAssemblies = TargetAssembly.GetReferencedAssemblies(); ReferenceAssemblies = referenceAssemblies.Aggregate( new SortedDictionary <string, Assembly>(), (acc, e) => { acc.Add(e.Name, Assembly.Load(e)); return(acc); } ); var tmp = package.Split('/'); var id = tmp[0]; var packageName = tmp[1]; var mainScriptPath = Path.Combine(PackageDirectory, package, patchName, "Main.cs"); #if DEBUG // for debugging purpose // mainScriptPath = @"C:\Touhou-Dotnet-Patches\lang-vi\thfdf\Main.cs"; #endif log.Log("Begin loading patching script..."); log.Log($"DebugMode = {DebugBuild}"); var mutex = new Mutex(false, ConfigurationManager.AppSettings["SharedLock"], out bool createdNew); var updater = options.UpdateOnStart && createdNew ? new Updater(targetPath, id, packageName, patchName, RootDirectory, PackageDirectory, options) : null; if (!createdNew) { log.Log("An instance of Configurator or Updater is already running!"); } if (updater != null) { log.Log("Run Updater..."); } var updatingTask = updater?.RunAsync(); pd.Value = 10; pd.Line1 = "Biên dịch tệp script"; log.Log($"Load {mainScriptPath}"); CSScriptHack.InjectObjectForPrecompilers(new Hashtable() { { "Version", TargetVersion }, }); var package_dirs = new ScriptParser(mainScriptPath, null).ResolvePackages() .Select(Path.GetDirectoryName) .ToList(); package_dirs.ForEach(CSScript.GlobalSettings.AddSearchDir); var refAsms = ReferenceAssemblies.Select(asm => asm.Value.Location).ToArray(); refAsms = new string[0]; var script = new AsmHelper(CSScript.LoadFile( mainScriptPath, null, DebugBuild, refAsms)); Directory.SetCurrentDirectory(TargetDirectory); pd.Value = 20; pd.CloseDialog(); log.Log("Call DotnetPatching.Config.OnInit"); dynamic status = script.GetStaticMethod("DotnetPatching.Config.OnInit")(); if (status == false) { goto EnableUpdateButtonStep; } pd = new ProgressDialog(IntPtr.Zero); pd.Title = "Đang tải dữ liệu"; pd.Maximum = 100; pd.Value = 0; pd.Line1 = "Thiết đặt Harmony"; pd.Line2 = "Xin vui lòng chờ trong giây lát..."; pd.Line3 = " "; pd.ShowDialog(ProgressDialog.PROGDLG.Modal, ProgressDialog.PROGDLG.NoMinimize); pd.Value = 30; log.Log("Call DotnetPatching.Detours.OnSetup"); var OnSetup = script.GetStaticMethod("DotnetPatching.Detours.OnSetup"); var detourList = (List <PatchTuple>)OnSetup(); log.Log("Call DotnetPatching.Transpilers.OnSetup"); OnSetup = script.GetStaticMethod("DotnetPatching.Transpilers.OnSetup"); var transpilerList = (List <TranspilerTuple>)OnSetup(); var total = detourList.Count + transpilerList.Count; log.Log("Begin setting up Detour Functions..."); pd.Line2 = "Setting up Detour Functions"; SetupHook(detourList, (count, message) => { pd.Line3 = message; pd.Value = (uint)(30 + 70 * count / total); }); log.Log("Begin setting up Transpilers to modify functions..."); SetupTranspiler(transpilerList, (count, message) => { pd.Line3 = message; pd.Value = (uint)(30 + 70 * count / total); }); log.Log("Launch the target executable..."); pd.Value = 100; pd.CloseDialog(); TargetAssembly.EntryPoint.Invoke(null, new object[] { new string[] { } }); EnableUpdateButtonStep: log.Log("Enable updating."); if (updatingTask != null) { updater.EnableUpdateButton(); log.Log("Wait for updater to complete."); updatingTask.Wait(); updater.Close(); } mutex.Dispose(); log.Log("Dotnet Runtime Patcher main thread ends."); log.Close(); }