C3204
2026-01-28 693a6135b4762c20c01b5df52ea2da9ae73f237b
LB_SmartVision/VisionForm.cs
@@ -10,6 +10,7 @@
using LB_SmartVision.Forms.Pages.SettingPage;
using LB_SmartVision.Forms.Pages.UserManagementPage;
using LB_SmartVision.ProcessRun;
using LB_SmartVision.SQL;
using LB_SmartVision.Tool;
using LB_SmartVisionCommon;
using LB_SmartVisionLoginUI;
@@ -633,7 +634,15 @@
            {
                LogInfo("全局变量加载失败", LogInfoType.ERROR);
            }
            GlobalVar.dicMotionControlData.Clear();
            if (LoadMotionControlDatas(GlobalVar.allMotionControlDataPath))
            {
                LogInfo("运动控制参数加载成功", LogInfoType.PASS);
            }
            else
            {
                LogInfo("运动控制参数加载失败", LogInfoType.ERROR);
            }
            //加载流程
            GlobalVar.dicProcesses.Clear();
            if (LoadAllProcess(GlobalVar.allProcessConnectionStringPath))
@@ -687,6 +696,7 @@
            com_ProductName.Items.Add("新增");
            com_ProductName.Text = GlobalVar.strProductName;
            this.WindowState = FormWindowState.Maximized;
            DatabaseRecordProductDataHelper.InitializeDatabase();
        }
        public void SaveAllSetting()
@@ -698,6 +708,54 @@
            SaveAllProcessSetting();
            SaveAllLayout();
            SaveAllCsv();
            SaveMotionControlDatas();
        }
        public bool LoadMotionControlDatas(string alMotionControlDataPath)
        {
            try
            {
                GlobalVar.dicMotionControlData = ConfigManager<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>.LoadConfig<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>(alMotionControlDataPath);
            }
            catch
            {
                return false;
            }
            return true;
        }
        public bool SaveMotionControlDatas()
        {
            try
            {
                ConcurrentDictionary<string, List<string>> removeCameraSN = new ConcurrentDictionary<string, List<string>>();
                foreach (var item in GlobalVar.dicMotionControlData.Keys)
                {
                    List<string> list = new List<string>();
                    foreach (var itemSN in GlobalVar.dicMotionControlData[item].Keys)
                    {
                        if (!GlobalVar.dicCameras.Keys.Contains(itemSN))
                        {
                            list.Add(itemSN);
                        }
                    }
                    if (list.Count > 0)
                    {
                        removeCameraSN.TryAdd(item, list);
                    }
                }
                foreach (var item in removeCameraSN.Keys)
                {
                    foreach (var itemSN in removeCameraSN[item])
                    {
                        GlobalVar.dicMotionControlData[item].Keys.Remove(itemSN);
                    }
                }
                ConfigManager<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>.SaveConfig<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>(GlobalVar.dicMotionControlData, GlobalVar.allMotionControlDataPath);
            }
            catch
            {
                return false;
            }
            return true;
        }
        public bool LoadAllCameras(string allCamerasConnectionStringPath)
@@ -841,12 +899,8 @@
                    if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7"))
                    {
                        // 定义正则表达式以提取协议、IP 地址和端口
                        //1.    \((.*?)\):\(和 \) 是用于匹配括号的转义字符。
                        //      (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。
                        //2.    ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。
                        //3.    (\d +) :匹配端口号,确保它匹配一个或多个数字。
                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\]$";
                        // 更新正则以支持可选的数据类型字段
                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$";
                        Match match = Regex.Match(CommunicatorAddress, pattern);
                        if (match.Success)
@@ -854,8 +908,10 @@
                            string ClassName = match.Groups["ClassName"].Value;   // "TCP"
                            string IP = match.Groups["IP"].Value;          // "127.0.0.1"
                            string Slot = match.Groups["Slot"].Value;        // "1111"
                            string CpuType= match.Groups["CpuType"].Value;
                            string CpuType = match.Groups["CpuType"].Value;
                            string PlcAddress = match.Groups["PlcAddress"].Value;
                            string DataType = match.Groups["DataType"].Success ? match.Groups["DataType"].Value : "String";
                            if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Slot) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
                                break;
@@ -878,6 +934,7 @@
                            Communicator.CommunicatorConnections.Add("端口", Slot);
                            Communicator.CommunicatorConnections.Add("型号", CpuType);
                            Communicator.CommunicatorConnections.Add("变量地址", PlcAddress);
                            Communicator.CommunicatorConnections.Add("数据类型", DataType);
                            Communicator.CommunicatorName = CommunicatorName;
                            if (!Communicator.Connect())
                            {
@@ -1028,7 +1085,6 @@
            {
                string strJson = string.Empty;
                GlobalVar.allCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
                foreach (var item in GlobalVar.dicCommunicators)
                {
                    string ClassName = item.Value.GetType().FullName;// "TCP"
@@ -1038,11 +1094,14 @@
                    {
                        string CpuType = item.Value.CommunicatorConnections["型号"].ToString();
                        string PlcAddress = item.Value.CommunicatorConnections["变量地址"].ToString();
                        string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ?
                                          item.Value.CommunicatorConnections["数据类型"].ToString() : "String";
                        if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
                        {
                            break;
                        }
                        string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}]";
                        string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}][{DataType}]";
                        GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
                    }
                    else
@@ -1054,6 +1113,7 @@
                        string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}]";
                        GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
                    }
                    GlobalVar.dicCommunicators[item.Key].ClassName = ClassName;
                }
                var settings = new JsonSerializerSettings
                {
@@ -1078,6 +1138,11 @@
                    { }
                }
                File.WriteAllText(GlobalVar.allCommunicatorsConnectionStringPath, strJson, Encoding.UTF8);
                foreach (var item in GlobalVar.dicCommunicators)
                {
                    string ClassName = item.Value.GetType().FullName;// "TCP"
                }
                ConfigManager<ObservableConcurrentDictionary<string, BaseCommunicator>>.SaveConfig<ObservableConcurrentDictionary<string, BaseCommunicator>>(GlobalVar.dicCommunicators, GlobalVar.strApplicationPath + "\\所有产品\\" + GlobalVar.strProductName + "\\dicCommunicators.json");
                return true;
            }
            catch { return false; }
@@ -1337,6 +1402,7 @@
                GlobalVar.strProductName = com_ProductName.SelectedItem?.ToString();
                foreach (BaseCamera camera in GlobalVar.dicCameras.Values)
                {
                    camera.TriggerRunMessageReceived -= TriggerRunMessageReceived;
                    camera.Dispose();
                }
                GlobalVar.dicCameras.Clear();
@@ -1650,6 +1716,128 @@
                communicator.Disconnect();
            }
            FormClosing -= VisionForm_FormClosing;
            //try
            //{
            //    Process[] processes = System.Diagnostics.Process.GetProcesses(); //获得所有进程
            //    foreach (Process p in processes)
            //    {
            //        if (p.ProcessName == "LB_SmartVision" && p.StartTime < DateTime.Now.AddMilliseconds(-300))
            //        {
            //            p.Kill();
            //        }
            //    }
            //}
            //catch { }
            KillAllTargetProcesses();
        }
        /// <summary>
        /// 杀进程逻辑
        /// </summary>
        private void KillAllTargetProcesses()
        {
            try
            {
                // 1. 获取当前进程ID,避免杀死自己
                int currentProcessId = Process.GetCurrentProcess().Id;
                // 2. 模糊匹配进程名(忽略大小写),覆盖vshost/后缀等情况
                var targetProcesses = Process.GetProcesses()
                    .Where(p =>
                        p.ProcessName.IndexOf("LB_SmartVision", StringComparison.OrdinalIgnoreCase) >= 0
                        && p.Id == currentProcessId);
                foreach (var p in targetProcesses)
                {
                    try
                    {
                        if (!p.HasExited)
                        {
                            // 先尝试优雅关闭WinForm程序(比直接Kill更友好)
                            p.CloseMainWindow();
                            // 等待500ms,看是否正常退出
                            if (!p.WaitForExit(500))
                            {
                                p.Kill(); // 强制杀死
                                p.WaitForExit(1000); // 等待进程完全终止
                            }
                        }
                        p.Dispose(); // 释放进程资源,避免句柄泄漏
                    }
                    catch (Exception ex)
                    {
                        // 记录异常但不中断,比如权限不足的情况
                        System.IO.File.AppendAllText("kill_process_log.txt", $"[{DateTime.Now}] 杀死进程失败: {ex.Message}\r\n");
                    }
                }
                // 额外延迟,确保文件句柄完全释放
                Thread.Sleep(1000);
            }
            catch (Exception)
            {
                // 静默失败,不影响程序退出
            }
        }
        private void btn_Run_Click(object sender, EventArgs e)
        {
            var matchedItems = GlobalVar.dicProcessSetting
                                        .Where(item =>
                                        {
                                            var value = item.Value;
                                            var triggerComm = value["触发通讯"];
                                            var triggerChar = value["触发字符"];
                                            return triggerComm != null;
                                            //return triggerComm != null && triggerComm.Equals(name) &&
                                            //       (string.IsNullOrEmpty(triggerChar?.ToString()) ||
                                            //        msg.StartsWith(triggerChar.ToString()));
                                        })
                                        .ToList(); // 避免重复字典访问和装箱操作
            if (matchedItems.Count <= 0)
            {
                return;
            }
            TriggerRunMessageReceived(matchedItems[0].Value["触发通讯"], matchedItems[0].Value["触发字符"]);
        }
        private void btn_RunContinuously_Click(object sender, EventArgs e)
        {
            if (btn_RunContinuously.Text.Equals("连续运行"))
            {
                btn_RunContinuously.Text = "暂停运行";
                Task.Factory.StartNew(() =>
                {
                    var matchedItems = GlobalVar.dicProcessSetting
                                                .Where(item =>
                                                {
                                                    var value = item.Value;
                                                    var triggerComm = value["触发通讯"];
                                                    var triggerChar = value["触发字符"];
                                                    return triggerComm != null;
                                                    //return triggerComm != null && triggerComm.Equals(name) &&
                                                    //       (string.IsNullOrEmpty(triggerChar?.ToString()) ||
                                                    //        msg.StartsWith(triggerChar.ToString()));
                                                })
                                                .ToList(); // 避免重复字典访问和装箱操作
                    while (btn_RunContinuously.Text.Equals("暂停运行"))
                    {
                        TriggerRunMessageReceived(matchedItems[0].Value["触发通讯"], matchedItems[0].Value["触发字符"]);
                        Thread.Sleep(500);
                    }
                    //this.Invoke(() =>
                    //{
                    //});
                });
            }
            else if (btn_RunContinuously.Text.Equals("暂停运行"))
            {
                btn_RunContinuously.Text = "连续运行";
                Thread.Sleep(100);
            }
        }
    }
}