|
|
@@ -1,14 +1,114 @@
|
|
|
using System;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Threading;
|
|
|
+using ivf_tl_Control; // AppData, StartMain
|
|
|
+using IvfTl.Control.Services; // Log4netHelper(程序集 ivf_tl_Control_Services;切勿写 operate 端 ivf_tl_Services)
|
|
|
|
|
|
namespace IvfTl.ControlHost
|
|
|
{
|
|
|
public static class Program
|
|
|
{
|
|
|
+ private static Mutex _singleton;
|
|
|
+ private static ControlHttpServer _http;
|
|
|
+ private static volatile bool _started;
|
|
|
+ private static ManualResetEventSlim _exitEvent;
|
|
|
+
|
|
|
[STAThread]
|
|
|
public static int Main(string[] args)
|
|
|
{
|
|
|
- Console.WriteLine("ivf_tl_ControlHost starting, args=" + string.Join(" ", args));
|
|
|
- return 0;
|
|
|
+ // 1) 单实例:已有 control 在跑则立即退出(永远只有一个驱动机器)。
|
|
|
+ bool isNew;
|
|
|
+ _singleton = new Mutex(true, @"Global\ivf_tl_control_singleton", out isNew);
|
|
|
+ if (!isNew)
|
|
|
+ {
|
|
|
+ Log4netHelper.WriteLog("ControlHost: 已有实例在运行,本进程退出");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var hostArgs = HostArgs.Parse(args);
|
|
|
+ Log4netHelper.WriteLog($"ControlHost 启动 port={hostArgs.Port} account={hostArgs.Account}");
|
|
|
+
|
|
|
+ // 2) 先起 HTTP(让 operate 能尽早探到"在启动中"),started=false。
|
|
|
+ _http = new ControlHttpServer(
|
|
|
+ hostArgs.Port,
|
|
|
+ BuildStatus,
|
|
|
+ msg => Log4netHelper.WriteLog(msg));
|
|
|
+ _http.Start();
|
|
|
+
|
|
|
+ // 3) 账号守卫(对齐 operate 空账号跳过逻辑)。
|
|
|
+ if (!hostArgs.IsValid)
|
|
|
+ {
|
|
|
+ Log4netHelper.WriteLog("ControlHost: 账号/密码为空,不启动采集(仅 HTTP 存活)");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 4) 复刻 operate MainWindow 启动序(顺序不可变)。
|
|
|
+ if (!AppData.Instance.Login(hostArgs.Account, hostArgs.Password))
|
|
|
+ {
|
|
|
+ Log4netHelper.WriteLog("ControlHost: control 登录失败");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(hostArgs.CacheDisk))
|
|
|
+ {
|
|
|
+ ivf_tl_UtilHelper.PathHelper.pan = hostArgs.CacheDisk;
|
|
|
+ AppData.Instance.LogService.Pan = hostArgs.CacheDisk;
|
|
|
+ }
|
|
|
+ try
|
|
|
+ {
|
|
|
+ IvfTl.Hardware.Impl.HardwareAccessLayer.Instance.Log =
|
|
|
+ msg => Log4netHelper.WriteLog(msg);
|
|
|
+ var devices = IvfTl.Hardware.Impl.HardwareAccessLayer.Instance.ScanDevices();
|
|
|
+ Log4netHelper.WriteLog($"ControlHost: HAL 发现 {devices.Count} 个舱");
|
|
|
+ }
|
|
|
+ catch (Exception hex)
|
|
|
+ {
|
|
|
+ Log4netHelper.WriteLog("ControlHost: HAL 发现异常(降级):" + hex.Message);
|
|
|
+ }
|
|
|
+
|
|
|
+ var startMain = new StartMain();
|
|
|
+ string err = startMain.StartRun(); // 阻塞:InitTL→InitHouse→StartAsync
|
|
|
+ if (!string.IsNullOrEmpty(err))
|
|
|
+ Log4netHelper.WriteLog("ControlHost: control 启动失败:" + err);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _started = true;
|
|
|
+ Log4netHelper.WriteLog("ControlHost: control 启动成功,常驻运行");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5) 驻留:control 后台线程已起(LongRunning),主线程阻塞等退出信号。
|
|
|
+ _exitEvent = new ManualResetEventSlim(false);
|
|
|
+ _exitEvent.Wait();
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Log4netHelper.WriteLog("ControlHost 致命异常", ex);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ try { _http?.Stop(); } catch { }
|
|
|
+ try { _singleton?.ReleaseMutex(); } catch { }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>提供给 HTTP /status 的快照(阶段1:基础存活;阶段2 接 GetMonitorSnapshot 补全)。</summary>
|
|
|
+ private static StatusDto BuildStatus()
|
|
|
+ {
|
|
|
+ string tlSn = "";
|
|
|
+ try { tlSn = AppData.Instance.TLSetting?.tlSn ?? ""; } catch { }
|
|
|
+ return new StatusDto
|
|
|
+ {
|
|
|
+ Ok = true,
|
|
|
+ Pid = Process.GetCurrentProcess().Id,
|
|
|
+ TlSn = tlSn,
|
|
|
+ Started = _started
|
|
|
+ };
|
|
|
}
|
|
|
}
|
|
|
}
|