This repository has been archived on 2026-10-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

111 lines
5.2 KiB
C#
Raw Permalink Normal View History

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
// 入口。正常双击 => 打开界面;带 /dryrun => 只做路径自检并把结果写进 launcher.log,不弹界面、不启动任何进程。
internal static class Program
{
[STAThread]
private static int Main(string[] args)
{
foreach (var a in args)
{
var t = (a ?? "").Trim().ToLowerInvariant();
if (t == "/dryrun" || t == "--dryrun" || t == "-dryrun") return DryRun();
if (t == "/uitest" || t == "--uitest" || t == "-uitest") return UiTest(args);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
return 0;
}
// 界面冒烟测试:真的把 MainForm 造出来、Show 出来、跑几轮消息循环,
// 再把客户区 DrawToBitmap 存成 uitest.png。用来在没法肉眼看界面的环境里
// 既能证明「构造 + 布局 + 定时器」不炸,又能真的看到界面长什么样。
private static int UiTest(string[] args)
{
// --uitest-stop:拍完自然态后,再强制把服务端按键推成「关闭服务端」态拍第二张。
// 服务端当前没跑时,光靠 --uitest 是看不到「关闭服务端」外观的(红色停止图标)。
bool wantStop = false;
foreach (var a in args)
{
var t = (a ?? "").Trim().ToLowerInvariant();
if (t == "--uitest-stop" || t == "-uitest-stop") wantStop = true;
}
string root = AppContext.BaseDirectory.TrimEnd('\\', '/');
string log = Path.Combine(root, "tools", "launcher", "launcher.log");
void L(string s)
{
try { File.AppendAllText(log, DateTime.Now.ToString("HH:mm:ss") + " " + s + Environment.NewLine); } catch { }
}
string png = Path.Combine(root, "uitest.png");
static void Snap(Form f, string path)
{
using var bmp = new Bitmap(f.ClientSize.Width, f.ClientSize.Height);
f.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
bmp.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using var f = new MainForm();
f.Opacity = 1;
L("[UITEST] 1 构造完成");
// ⛑ 必须真的 Show 一次,否则子控件不会 Realize,DrawToBitmap 只拍得到窗体自绘层。
// 挪到屏幕外,避免在用户桌面上闪一下。
f.StartPosition = FormStartPosition.Manual;
f.Location = new Point(-4000, -4000);
f.Show();
for (int i = 0; i < 10; i++) { Application.DoEvents(); System.Threading.Thread.Sleep(20); }
f.PerformLayout();
L("[UITEST] 2 已显示,Size=" + f.ClientSize.Width + "x" + f.ClientSize.Height);
Application.DoEvents();
Snap(f, png);
if (wantStop)
{
// ⛑ 强推状态后「立刻」拍,中间不能 DoEvents —— 否则 1 秒轮询会把按键改回自然态
f.ForceServerButtonForTest(true);
string png2 = Path.Combine(root, "uitest-stop.png");
Snap(f, png2);
L("[UITEST] 已强制「关闭服务端」态,截图 = " + png2);
}
f.Close();
L("[UITEST] 界面构造 + 布局 + 轮询 OK,截图 = " + png);
return 0; }
catch (Exception ex)
{
L("[UITEST] 异常: " + ex);
return 3;
}
}
private static int DryRun()
{
string root = AppContext.BaseDirectory.TrimEnd('\\', '/');
string log = Path.Combine(root, "tools", "launcher", "launcher.log");
void L(string s)
{
try { File.AppendAllText(log, DateTime.Now.ToString("HH:mm:ss") + " " + s + Environment.NewLine); } catch { }
}
L("============ DRYRUN(界面版) ============");
L("root = " + root);
string startCmd = Path.Combine(root, "START.cmd");
string injector = Path.Combine(root, "tools", "AnantaInjector", "unified_loader.py");
// ⛑ 优先随包分发的便携 python;没有再退回开发者本机的环境(避免分发给别人时报「找不到」)。
string python = Path.Combine(root, "tools", "python", "python.exe");
if (!File.Exists(python)) python = @"C:\Users\Noiro\.workbuddy\binaries\python\envs\default\Scripts\python.exe";
string serverCfg = Path.Combine(root, "config", "private-server.json");
L("START.cmd = " + startCmd + " exists=" + File.Exists(startCmd));
L("injector = " + injector + " exists=" + File.Exists(injector));
L("python = " + python + " exists=" + File.Exists(python));
L("serverCfg = " + serverCfg + " exists=" + File.Exists(serverCfg));
L("[DRYRUN] 路径自检完成,未启动任何进程。");
return File.Exists(startCmd) && File.Exists(injector) && File.Exists(python) ? 0 : 2;
}
}