alielie
2026-06-04 771a0e7b6b1276087515bbe94de28358cb92963b
Plugin.TsExecution/TsExecution.xaml.cs
@@ -6,11 +6,13 @@
using HMI.Core.Setting;
using HMI.Core.Util;
using HMI.MQUtil;
using HMI.Simple.Util;
using HMI.UI.Util;
using HMI.Util;
using log4net;
using NationalInstruments.TestStand.Interop.API;
using NationalInstruments.TestStand.Interop.UI.Ax;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using Plugin.TsSupport;
using ScottPlot;
using ScottPlot.Plottables;
@@ -20,8 +22,6 @@
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.DataVisualization.Charting;
@@ -37,24 +37,23 @@
        /// <summary>
        /// TS 引擎
        /// </summary>
        private Engine engine = null;
        //private Engine engine = null;
        ///// <summary>
        ///// 测试序列
        ///// </summary>
        //private SequenceFile testSeq = null;
        ///// <summary>
        ///// 测试模型序列
        ///// </summary>
        //private SequenceFile modeSeq = null;
        //private Execution execution = null;
        private string testSeqFile = string.Empty;
        /// <summary>
        /// 测试序列
        /// </summary>
        private SequenceFile testSeq = null;
        /// <summary>
        /// 测试模型序列
        /// </summary>
        private SequenceFile modeSeq = null;
        public AxApplicationMgr AxApplicationMgr;
        private Execution execution = null;
        private SequenceContext sequenceContext = null;
        private Chart chart;
        private ITestExecutionWrapper testExecutionWrapper;
        #endregion
        public static ILog logger { get; private set; }
@@ -83,7 +82,6 @@
        private bool isLoadOK = false;
        private Timer GCTimer;
        private int PassAmount = 0;
        private int FailAmount = 0;
@@ -109,6 +107,7 @@
                    foreach (SingleControl socket in tsSockets)
                    {
                        socket.RefreshProduct(value);
                        // socket.RefreshProbeCount(value);
                    }
                }
                SetTestSeqFile(value);
@@ -182,9 +181,12 @@
            get => _enableCanLog;
            set
            {
                if (WriteConfig("EnableCanLog", value))
                if (RequirePassword() == true)
                {
                    Set(ref _enableCanLog, value);
                    if (WriteConfig("EnableCanLog", value))
                    {
                        Set(ref _enableCanLog, value);
                    }
                }
            }
        }
@@ -227,10 +229,13 @@
            get => _enableSimpleMode;
            set
            {
                if (WriteConfig("EnableSimpleMode", value))
                if (RequirePassword() == true)
                {
                    Set(ref _enableSimpleMode, value);
                    foreach (var cell in tsSockets) cell.SetSimpleUI(value);
                    if (WriteConfig("EnableSimpleMode", value))
                    {
                        Set(ref _enableSimpleMode, value);
                        foreach (var cell in tsSockets) cell.SetSimpleUI(value);
                    }
                }
            }
        }
@@ -241,10 +246,13 @@
            get => _ui_showInfoDock;
            set
            {
                if (WriteConfig("UI_ShowInfoDock", value))
                if (RequirePassword() == true)
                {
                    Set(ref _ui_showInfoDock, value);
                    detailPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
                    if (WriteConfig("UI_ShowInfoDock", value))
                    {
                        Set(ref _ui_showInfoDock, value);
                        detailPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
                    }
                }
            }
        }
@@ -268,8 +276,8 @@
                if (WriteIni("UI_CurrentWorkorder", value))
                {
                    Set(ref currentWorkorder, value);
                    engine?.Globals.SetValString("StationState.WorkOrder", 1, value);
                    engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false);
                    testExecutionWrapper?.SetStationGlobalValue("StationState.WorkOrder", 1, value);
                    testExecutionWrapper?.CommitToDisk(false);
                }
            }
        }
@@ -280,9 +288,12 @@
            get => _DisableScanner;
            set
            {
                if (WriteConfig("DisableScanner", value))
                if (RequirePassword() == true)
                {
                    Set(ref _DisableScanner, value);
                    if (WriteConfig("DisableScanner", value))
                    {
                        Set(ref _DisableScanner, value);
                    }
                }
            }
        }
@@ -297,13 +308,10 @@
        public TsExecution()
        {
            DataContext = this;
            GCTimer = new Timer();
            InitializeComponent();
            InitChart();
            InitTsEngine();
            //初始化TestStand引擎
            this.InitTestStandEngine();
        }
        public override void SetBaseFolder(string folder)
@@ -373,8 +381,9 @@
            {
                UserInfo user = UserInfo.User;
                CurrentUserCode = user?.Code;
                engine?.Globals.SetValString("StationState.OPID", 1, CurrentUserCode);
                engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false);
                testExecutionWrapper?.SetStationGlobalValue("StationState.OPID", 1, CurrentUserCode);
                testExecutionWrapper?.CommitToDisk(false);
            }
            catch (Exception ex)
            {
@@ -443,7 +452,7 @@
            Products = ProductManager.GetProducts<ObservableCollection<ProductData>>();
            if (Products != null && Products.Count > 0)
            {
                string lastModel = engine?.Globals.GetValString("StationState.ProductModel", 1);
                string lastModel = testExecutionWrapper?.GetStationGlobalValue<string>("StationState.ProductModel", 1);
                var tempProduct = Products[0];
                if (!string.IsNullOrEmpty(lastModel))
                {
@@ -487,25 +496,58 @@
        /// </summary>
        private void InitTsEngine()
        {
            AxApplicationMgr = TestAppManager.GetAxApplicationMgr();
            if (ParamSetting.EngineType == "Tap")
            {
                testExecutionWrapper = new TapWrapper();
            }
            else
            {
                testExecutionWrapper = new TeststandWrapper();
            }
            //AxApplicationMgr. += AxApplicationMgr_EndExecution;
            AxApplicationMgr.EndExecution += AxApplicationMgr_EndExecution;
            AxApplicationMgr.ExitApplication += this.AxApplicationMgr_ExitApplication;
            AxApplicationMgr.UIMessageEvent += this.AxApplicationMgr_UIMessageEvent;
            AxApplicationMgr.ExecutionClosed += this.AxApplicationMgr_ExecutionClosed;
            ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit();
            host.Child = AxApplicationMgr;
            ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit();
            testExecutionWrapper.EndExecutionEvent += TestExecutionWrapper_EndExecutionEvent;
            testExecutionWrapper.UIMessageEvent += TestExecutionWrapper_UIMessageEvent;
            if (testExecutionWrapper is TeststandWrapper tsw)
            {
                var AxApplicationMgr = tsw.AxApplicationMgr;
                ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit();
                host.Child = AxApplicationMgr;
                ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit();
            }
            testExecutionWrapper.Init();
        }
        private volatile bool canSwitchModel = false;
        private volatile Action switchAction = null;
        private void TestExecutionWrapper_UIMessageEvent(object sender, UIMessageEvent e)
        {
            try
            {
                int eventCode = Convert.ToInt32(e.EventCode);
                int index = Convert.ToInt16(e.NumberData);//SocketIndex
                string strData = e.StrData;
        private void AxApplicationMgr_EndExecution(object sender, _ApplicationMgrEvents_EndExecutionEvent e)
                try
                {
                    log.Debug($"Event: {eventCode}, NumericData: {index}, StringData: {strData}");
                }
                catch
                {
                }
                if (eventCode == 10001)
                {
                    testExecutionWrapper?.SetContext((SequenceContext)e.Data);
                    tsSockets[index].SequenceFileContext = (SequenceContext)e.Data;
                    return;
                }
                HandleUIMessage(eventCode, index, strData);
            }
            catch (Exception ex)
            {
                log.Warn("Ts Event Error.", ex);
            }
        }
        private void TestExecutionWrapper_EndExecutionEvent(object sender, ExecutionEndEvent e)
        {
            log.Info("AxApplicationMgr_EndExecution");
            if (ReleaseSequenceFile())
@@ -520,15 +562,8 @@
            }
        }
        /// <summary>
        /// 进程结束事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AxApplicationMgr_ExecutionClosed(object sender, _ApplicationMgrEvents_ExecutionClosedEvent e)
        {
            //ReleaseSequenceFile();
        }
        private volatile bool canSwitchModel = false;
        private volatile Action switchAction = null;
        private void PluginControl_Loaded(object sender, RoutedEventArgs e)
        {
@@ -547,17 +582,6 @@
                {
                    log.Error("TsExecution Loaded Failed.", ex);
                    MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.UserControlLoadFailed")}: {ex.Message}");
                }
                try
                {
                    if (Environment.Version.ToString() != this.AxApplicationMgr.GetEngine().DotNetCLRVersion)
                        this.GCTimer.Enabled = true;
                }
                catch (Exception ex)
                {
                    log.Error("TsExecution GCTimer Start Failed", ex);
                    MsgBoxHelper.Error(this, $"{LangUtil.Get("Ts.LoadFailed")}: {ex.Message}");
                }
                Dispatcher.Invoke(() =>
@@ -653,26 +677,6 @@
        }
        /// <summary>
        /// 初始化TestStand引擎
        /// </summary>
        private void InitTestStandEngine()
        {
            try
            {
                this.engine = this.AxApplicationMgr.GetEngine();
                this.engine.PersistBreakpoints = false;
                this.AxApplicationMgr.IsEditor = true;
                this.AxApplicationMgr.LoginOnStart = false;
                this.AxApplicationMgr.Start();
                //this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
            }
            catch (Exception ex)
            {
                throw new Exception(LangUtil.Get("Ts.InitTestStandEngineFail"), ex);
            }
        }
        /// <summary>
        /// 读取Count配置文件的pass和fail数
        /// </summary>
        /// <param name="pass">合格数</param>
@@ -695,7 +699,7 @@
        /// <param name="fail"></param>
        private void ReadConfig()
        {
            ParameterData value;
            HMI.Core.Entity.ParameterData value;
            bool flag = false;
@@ -955,7 +959,7 @@
                    foreach (var ts in tsSockets)
                    {
                        ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.{name}", 1, value);
                        if (ts?.SequenceFileContext?.Sequence != null)
                        if (name == "EnableDebugMode" && ts?.SequenceFileContext?.Sequence != null)
                        {
                            ts.SequenceFileContext.Sequence.FailureAction =
                                value ? FailureActions.FailureAction_None : FailureActions.FailureAction_GotoCleanup;
@@ -1065,7 +1069,7 @@
            if (!isLoadOK) return;
            try
            {
                engine?.Globals.SetValBoolean("StationState.StopTest", 1, false);
                testExecutionWrapper?.SetStationGlobalValue("StationState.StopTest", 1, false);
            }
            catch (Exception ex)
            {
@@ -1085,9 +1089,10 @@
                        return;
                    }
                    this.testSeqFile = path;
                    this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath);
                    this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType);
                    this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null);
                    testExecutionWrapper?.StartSequence(this.testSeqFile, this.tsModelPath);
                    //this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath);
                    //this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType);
                    //this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null);
                    IsTesting = true;
                }
                catch (Exception ex)
@@ -1104,11 +1109,12 @@
                //MaskWindow mask = new MaskWindow();
                try
                {
                    engine?.Globals.SetValString("StationState.ProductModel", 1, CurrentProductModel);
                    engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false);
                    this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath);
                    this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType);
                    this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null);
                    testExecutionWrapper?.SetStationGlobalValue("StationState.ProductModel", 1, CurrentProductModel);
                    testExecutionWrapper?.CommitToDisk(false);
                    testExecutionWrapper?.StartSequence(this.testSeqFile, this.tsModelPath);
                    //this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath);
                    //this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType);
                    //this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null);
                    IsTesting = true;
                }
                catch (Exception ex)
@@ -1143,21 +1149,14 @@
        {
            try
            {
                //if (this.tsSockets.Count > 0)
                //{
                //    for (int i = 0; i < tsSockets.Count; i++)
                //    {
                //        var context = this.tsSockets[i].SequenceFileContext;
                //        context?.StationGlobals.SetValBoolean("StationState.StopTest", 1, true);
                //    }
                //}
                engine.Globals.SetValBoolean("StationState.StopTest", 1, true);
                if (this.execution == null) return true;
                testExecutionWrapper.SetStationGlobalValue("StationState.StopTest", 1, true);
                //bool res = this.execution.WaitForEndEx(-1, true, null, null);
                bool res = this.execution?.WaitForEndEx(-1, true, Type.Missing, null) == true;
                Marshal.ReleaseComObject(this.execution);
                this.execution = null;
                bool res = this.testExecutionWrapper.WaitForExit();
                //if (this.execution != null)
                //    Marshal.ReleaseComObject(this.execution);
                //this.execution = null;
                return res;
            }
            catch (Exception ex)
@@ -1217,22 +1216,229 @@
            //    }).Info(LangUtil.Get("Ts.SequenceIsStarting"));
        }
        /// <summary>
        /// 退出应用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AxApplicationMgr_ExitApplication(object sender, EventArgs e)
        {
            //Environment.ExitCode = this.AxApplicationMgr.ExitCode;
            //this.Close();
        }
        public void UpdatePositionStatus(int index, string status)
        {
            this.tsSockets[index].UpdateStatus(status);
            OnStatusPublished(index, status);
            this.UpdateTestCounter();
        }
        private void OnStatusPublished(int index, string status)
        {
            if (ParamSetting.CustomerCode != "SOUND")
            {
                return;
            }
            if (status == "Passed" || status == "Failed")
            {
                SaveSOUNDExcel(index, status);
            }
        }
        private string ConvertStatus(string status)
        {
            if (string.Equals(status, "passed", StringComparison.OrdinalIgnoreCase))
            {
                return "Pass";
            }
            else
            {
                return "Fail";
            }
        }
        #region 桑德定制
        private ICell CreateCell(ISheet sheet, int r, int c, ICellStyle style)
        {
            var row = sheet.GetRow(r);
            if (row == null)
            {
                row = sheet.CreateRow(r);
            }
            var cell = row.GetCell(c);
            if (cell == null)
            {
                cell = row.CreateCell(c);
            }
            if (style != null)
            {
                cell.CellStyle = style;
            }
            return cell;
        }
        private string GetOutputFolder()
        {
            var value = ParameterManager.GetCommonParameterByName("SOUND_Output");
            if (value != null)
            {
                return value.Value;
            }
            return ParamSetting.DataLogFolder;
        }
        private void SaveSOUNDExcel(int index, string status)
        {
            lock (this)
            {
                try
                {
                    string outputFolder = GetOutputFolder();
                    var socket = this.tsSockets[index];
                    DateTime testTime = DateTime.Now;
                    string filePath = Path.Combine(outputFolder, $"{testTime.ToString("yy-MM-dd")}_{CurrentProductModel}.xls");
                    if (!File.Exists(filePath))
                    {
                        Dictionary<string, int> columnMap = new Dictionary<string, int>();
                        HSSFWorkbook workbook = new HSSFWorkbook();
                        ISheet sheet = workbook.CreateSheet("Sheet1");
                        ICellStyle border = workbook.CreateCellStyle();
                        border.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                        border.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                        border.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                        border.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                        border.BottomBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                        border.TopBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                        border.LeftBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                        border.RightBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                        ICellStyle red = workbook.CreateCellStyle();
                        red.CloneStyleFrom(border);
                        red.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Red.Index;
                        red.FillPattern = FillPattern.SolidForeground;
                        ICellStyle green = workbook.CreateCellStyle();
                        green.CloneStyleFrom(border);
                        green.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.BrightGreen.Index;
                        green.FillPattern = FillPattern.SolidForeground;
                        CreateCell(sheet, 1, 0, border);
                        CreateCell(sheet, 1, 1, border);
                        CreateCell(sheet, 1, 2, border);
                        CreateCell(sheet, 1, 3, border);
                        CreateCell(sheet, 1, 4, border);
                        CreateCell(sheet, 2, 0, border);
                        CreateCell(sheet, 2, 1, border);
                        CreateCell(sheet, 2, 2, border);
                        CreateCell(sheet, 2, 3, border);
                        CreateCell(sheet, 2, 4, border).SetCellValue("上限");
                        CreateCell(sheet, 3, 0, border).SetCellValue("测试时间");
                        CreateCell(sheet, 3, 1, border).SetCellValue("测试人");
                        CreateCell(sheet, 3, 2, border).SetCellValue("测试设备");
                        CreateCell(sheet, 3, 3, border).SetCellValue("条形码");
                        CreateCell(sheet, 3, 4, border).SetCellValue("下限");
                        int column = 5;
                        int row = 4;
                        CreateCell(sheet, row, 0, border).SetCellValue(testTime.ToString("*HH:mm:ss*"));
                        CreateCell(sheet, row, 1, border).SetCellValue(UserInfo.User.Name);
                        CreateCell(sheet, row, 2, border).SetCellValue(ParamSetting.StationName);
                        CreateCell(sheet, row, 3, border).SetCellValue(socket.Barcode);
                        CreateCell(sheet, row, 4, status == "Passed" ? green : red).SetCellValue(ConvertStatus(status));
                        foreach (var data in socket.Datasource)
                        {
                            int col = column;
                            if (columnMap.ContainsKey(data.Name))
                            {
                                col = columnMap[data.Name];
                            }
                            else
                            {
                                columnMap[data.Name] = column++;
                            }
                            CreateCell(sheet, 1, col, border).SetCellValue(data.Name);
                            CreateCell(sheet, 2, col, border).SetCellValue(data.LimitUp);
                            CreateCell(sheet, 3, col, border).SetCellValue(data.LimitDown);
                            CreateCell(sheet, row, col, data.Result == "Failed" ? red : border).SetCellValue(data.Value);
                        }
                        using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
                        {
                            workbook.Write(fs);
                        }
                    }
                    else
                    {
                        using (FileStream fs = File.OpenRead(filePath))
                        {
                            IWorkbook workbook = new HSSFWorkbook(fs);
                            ICellStyle border = workbook.CreateCellStyle();
                            border.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                            border.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                            border.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                            border.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                            border.BottomBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                            border.TopBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                            border.LeftBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                            border.RightBorderColor = NPOI.HSSF.Util.HSSFColor.Black.Index;
                            ICellStyle red = workbook.CreateCellStyle();
                            red.CloneStyleFrom(border);
                            red.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Red.Index;
                            red.FillPattern = FillPattern.SolidForeground;
                            ICellStyle green = workbook.CreateCellStyle();
                            green.CloneStyleFrom(border);
                            green.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.BrightGreen.Index;
                            green.FillPattern = FillPattern.SolidForeground;
                            ISheet sheet = workbook.GetSheet("Sheet1");
                            Dictionary<string, int> columnMap = new Dictionary<string, int>();
                            var titleRow = sheet.GetRow(1);
                            for (int i = 0; i < titleRow.LastCellNum; i++)
                            {
                                if (!string.IsNullOrEmpty(titleRow.GetCell(i).StringCellValue))
                                {
                                    columnMap[titleRow.GetCell(i).StringCellValue] = i;
                                }
                            }
                            int row = sheet.LastRowNum + 1;
                            CreateCell(sheet, row, 0, border).SetCellValue(testTime.ToString("*HH:mm:ss*"));
                            CreateCell(sheet, row, 1, border).SetCellValue(UserInfo.User.Name);
                            CreateCell(sheet, row, 2, border).SetCellValue(ParamSetting.StationName);
                            CreateCell(sheet, row, 3, border).SetCellValue(socket.Barcode);
                            CreateCell(sheet, row, 4, status == "Passed" ? green : red).SetCellValue(ConvertStatus(status));
                            foreach (var data in socket.Datasource)
                            {
                                int col = titleRow.LastCellNum;
                                if (columnMap.ContainsKey(data.Name))
                                {
                                    col = columnMap[data.Name];
                                }
                                else
                                {
                                    columnMap[data.Name] = col;
                                }
                                CreateCell(sheet, 1, col, border).SetCellValue(data.Name);
                                CreateCell(sheet, 2, col, border).SetCellValue(data.LimitUp);
                                CreateCell(sheet, 3, col, border).SetCellValue(data.LimitDown);
                                CreateCell(sheet, row, col, data.Result == "Failed" ? red : border).SetCellValue(data.Value);
                            }
                            using (FileStream nfs = new FileStream(filePath, FileMode.OpenOrCreate))
                            {
                                workbook.Write(nfs);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.Error("SOUND Export Excel Data Error.", ex);
                }
            }
        }
        #endregion
        public void UpdatePositionProcessValue(int index, int value)
        {
@@ -1296,9 +1502,11 @@
                sqls.Add($@"INSERT INTO serialData (sn,model,station,step,position,limitDown,limitUp,unit,value,status,finalStatus,consumeTime,totalConsumeTime,time) VALUES
('{snr}','{model}','','{data.Name}','{index}','{data.LimitDown}','{data.LimitUp}','{data.Unit}','{data.Value}','{data.Result}','{socket.Status}','{data.ConsumeTime}','{socket.ElapseTime}','{time}')");
            }
            sqls.Add($@"INSERT INTO testResult (sn,model,station,result,time,position,status) VALUES
('{snr}','{model}','','{socket.Status}','{time}','{index}','{status}')");
            sqliteHelper.ExecuteBatchSql(sqls);
            var ssql = $@"INSERT INTO testResult (sn,model,station,result,time,position,status) VALUES
('{snr}','{model}','','{socket.Status}','{time}','{index}','{status}')";
            sqliteHelper.ExecuteSql(ssql);
        }
        private void HandleUIMessage(int eventCode, int index, string strData)
@@ -1385,6 +1593,26 @@
                    this.tsSockets[index].SetTestProcess(ProcessVal);
                    break;
                case 10031://导出CSV
                    if (ParamSetting.CustomerCode == "SOUND")
                    {
                        string[] datas = strData.Split(';');
                        this.tsSockets[index].WriteToExcel(datas[0]);
                        if (datas.Length >= 2)
                        {
                            SavePositionDB(index, datas[1]);
                        }
                        else
                        {
                            Dispatcher.Invoke(() =>
                            {
                                var sss = this.tsSockets[index].Status;
                                SavePositionDB(index, sss);
                            });
                        }
                        return;
                    }
                    if (string.IsNullOrEmpty(strData))
                    {
                        SaveTemplateCSV(index);
@@ -1400,8 +1628,11 @@
                        }
                        else
                        {
                            var sss = this.tsSockets[index].Status;
                            SavePositionDB(index, sss);
                            Dispatcher.Invoke(() =>
                            {
                                var sss = this.tsSockets[index].Status;
                                SavePositionDB(index, sss);
                            });
                        }
                    }
                    catch (Exception ex)
@@ -1435,6 +1666,22 @@
                        points[i - 1] = new int[2] { int.Parse(strs[0]), int.Parse(strs[1]) };
                    }
                    this.tsSockets[index].DrawScreenPoints(int.Parse(arr_10035[0]), points);
                    break;
                case 100350:
                    string[] arr_100350 = strData.Split(';');
                    int[][] points_0 = new int[arr_100350.Length - 1][];
                    for (int i = 1; i < arr_100350.Length; i++)
                    {
                        if (string.IsNullOrEmpty(arr_100350[i]))
                        {
                            continue;
                        }
                        string[] strs = arr_100350[i].Split(',');
                        points_0[i - 1] = new int[2] { int.Parse(strs[0]), int.Parse(strs[1]) };
                    }
                    this.tsSockets[index].DrawNewScreenPoints(int.Parse(arr_100350[0]), points_0);
                    break;
                case 10036:
                    this.tsSockets[index].ClearScreenPoint(int.Parse(strData));
@@ -1481,8 +1728,8 @@
                            {
                                log?.Info("开始自动换型");
                                SelectedProduct = target;
                                engine?.Globals.SetValString($"CacheSNR[{index}]", 1, snr);
                                engine?.CommitGlobalsToDisk(false);
                                testExecutionWrapper?.SetStationGlobalValue($"CacheSNR[{index}]", 1, snr);
                                testExecutionWrapper?.CommitToDisk(false);
                                StartClick();
                            }
                            catch (Exception ex)
@@ -1498,43 +1745,7 @@
        private void ShowAlarm(AlarmText alarm)
        {
            AlarmShowHelper.ShowAlarm(alarm);
            mSMQHelper.Send("Alarm", $"ATE测试 {alarm.AlarmInfo}");
        }
        /// <summary>
        /// TestStand用户交互事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AxApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e)
        {
            try
            {
                int eventCode = Convert.ToInt32(e.uiMsg.Event);
                int index = Convert.ToInt16(e.uiMsg.NumericData);//SocketIndex
                string strData = e.uiMsg.StringData;
                try
                {
                    log.Debug($"Event: {eventCode}, NumericData: {index}, StringData: {strData}");
                }
                catch
                {
                }
                if (eventCode == 10001)
                {
                    sequenceContext = (SequenceContext)e.uiMsg.ActiveXData;
                    tsSockets[index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData;
                    return;
                }
                HandleUIMessage(eventCode, index, strData);
            }
            catch (Exception ex)
            {
                log.Warn("Ts Event Error.", ex);
            }
            mSMQHelper.Send("Alarm", "PC", $"ATE测试 {alarm.AlarmInfo}", 2);
        }
        private void UpdateTestCounter()
@@ -1557,7 +1768,7 @@
                return;
            }
            string name = product.Name;
            List<ParameterData> parameters = ProductManager.GetParametersByProductName(name);
            List<HMI.Core.Entity.ParameterData> parameters = ProductManager.GetParametersByProductName(name);
            testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value?.ToString();
            if (AutoExecuteSeq)
            {
@@ -1607,32 +1818,13 @@
            {
                lock (this)
                {
                    if (this.testSeq == null)
                    {
                        return true;
                    }
                    //execution.Abort();
                    int count = 10;
                    while (count > 0)
                    {
                        try
                        {
                            if (this.testSeq == null)
                                return true;
                            if (this.engine?.ReleaseSequenceFileEx(this.testSeq, 4) == true)
                            {
                                Marshal.ReleaseComObject(this.testSeq);
                                this.testSeq = null;
                                // GC.Collect();
                            }
                            if (this.engine?.ReleaseSequenceFileEx(this.modeSeq, 4) == true)
                            {
                                Marshal.ReleaseComObject(this.modeSeq);
                                this.modeSeq = null;
                            }
                            this.engine?.UnloadAllModules();
                            return this.testSeq == null && this.modeSeq == null;
                            return testExecutionWrapper.ReleaseSeqFile();
                        }
                        catch (Exception ex)
                        {