ソースを参照

feat(control): Program.cs 完整启动序(Mutex+启动序+HTTP驻留)

阶段1-Task5:复刻 operate 启动序(Login→盘→ScanDevices→StartRun),
单实例 Mutex,HTTP 先起,主线程驻留。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie 3 日 前
コミット
ad449aea87
1 ファイル変更102 行追加2 行削除
  1. 102 2
      ivf_tl_operate_2.0/control/ivf_tl_ControlHost/Program.cs

+ 102 - 2
ivf_tl_operate_2.0/control/ivf_tl_ControlHost/Program.cs

@@ -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
+            };
         }
     }
 }