using Aspose.Cells; using Microsoft.Extensions.Caching.Memory; using System.Collections.Concurrent; using System.Data; using System.Diagnostics; using Txgy.RBS.DTO; using Txgy.RBS.Framework; using Txgy.RBS.Framework.Api; using Txgy.RBS.Framework.FileWatcherHelper; using Txgy.RBS.Framework.Models; using Txgy.RBS.Framework.RedisHelper.Service; using Txgy.RBS.IServices; namespace Txgy.RBS.Services { public class ProcessManagerService { private readonly IMemoryCache _cache; private readonly RedisListService _redisList; private readonly IResultInfoService _resultInfoService; public ProcessManagerService(RedisListService redisList, IResultInfoService resultInfoService, IMemoryCache cache) { MoniTimer.Interval = 10000; MoniTimer.Elapsed += MoniTimer_Elapsed; MoniTimer.Start(); this._redisList = redisList; this._resultInfoService = resultInfoService; _cache = cache; RedisServer = new ProcessInfo() { ProName = "server", StartTime = DateTime.Now, State = true }; } public ProcessInfo RedisServer { get; set; } private void MoniTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) { foreach (var item in ProjectMonitor) { _redisList.Publish(CommonData.RedisPublish, Newtonsoft.Json.JsonConvert.SerializeObject(new { projectName = item.Key, ProName = RedisServer.ProName, RunState = RedisServer.State?1:0, RunTime = (DateTime.Now - RedisServer.StartTime).TotalSeconds, })); foreach (var proValue in item.Value.GetType().GetProperties()) { var pro = proValue.GetValue(item.Value) as ProcessInfo; if (pro != null) { int sfp = FindProcess(pro); if (sfp != 0) { pro.State = false; Console.WriteLine($"{pro.ProName}程序重启中, path:{pro.ProPath}"); StartProcess(pro); Thread.Sleep(20); } else { pro.State = true; } _redisList.Publish(CommonData.RedisPublish, Newtonsoft.Json.JsonConvert.SerializeObject(new { projectName=item.Key, ProName = pro.ProName, RunState = sfp == 0 ? 1 : 0, RunTime = (DateTime.Now - pro.StartTime).TotalSeconds, })); } } } } public ConcurrentDictionary ProjectMonitor = new ConcurrentDictionary(); public void StartMointor(string projectName, ProcessConfig processInfo) { if (!ProjectMonitor.ContainsKey(projectName)) { ProjectMonitor.TryAdd(projectName, processInfo); processInfo.FilesWatcherService.InitializeParams(); processInfo.FilesWatcherService.Start(); processInfo.FilesWatcherService.WatcherFileChanged = WatcherChanged; } } System.Timers.Timer MoniTimer { get; set; } = new System.Timers.Timer(); public void StopMointor(string projectName) { if (ProjectMonitor.ContainsKey(projectName)) { ProjectMonitor.TryRemove(projectName, out ProcessConfig process); process.FilesWatcherService.Stop(); foreach (var proValue in process.GetType().GetProperties()) { var pro = proValue.GetValue(process) as ProcessInfo; if (pro != null) { _redisList.Publish(CommonData.RedisPublish, Newtonsoft.Json.JsonConvert.SerializeObject(new { projectName = projectName, ProName = pro.ProName, RunState = 0, RunTime = (DateTime.Now - pro.StartTime).TotalSeconds, })); } } } } void WatcherChanged(MsEventModel msEvent, FileSystemEventArgs e) { _resultInfoService.AddResultInfo(new ResultDTO { project_id = msEvent.ProjectId, otime = msEvent.OriginTime.ToString("O"), xlon = msEvent.EastCoordinate, ylat = msEvent.NorthCoordinate, depth = msEvent.Depth, ml = msEvent.ML, energy = msEvent.Energy, // rms=msEvent. phases_count = msEvent.PhasesCount, amps_count = msEvent.AmpsCount, }); _redisList.Publish($"{msEvent.ProjectName}result", Newtonsoft.Json.JsonConvert.SerializeObject(new { projectName = msEvent.ProjectName, otime = msEvent.OriginTime, message = msEvent.ToString(), jsonStr = "" })); } #region 方法 public ApiResult StartProject(string projectName, ProcessConfig processConfig) { int res = 0; if (ProjectMonitor.ContainsKey(projectName)) { return new ApiResult(); } foreach (var item in processConfig.GetType().GetProperties()) { var pro = item.GetValue(processConfig) as ProcessInfo; if (pro != null && pro.IsEnable) { res = StartProcess(pro); if (res != 0) { continue; } pro.StartTime = DateTime.Now; pro.State = true; // _cache.Set(pro.ProPath, pro); Thread.Sleep(10); } } StartMointor(projectName, processConfig); if (res == 0) { return new ApiResult(); } return new ApiResult() { Message = "操作失败" }; } public ApiResult StopProject(string projectName) { int res = 0; ProjectMonitor.TryGetValue(projectName, out ProcessConfig process); if(process == null) { return new ApiResult(); } foreach (var item in process.GetType().GetProperties()) { var pro = item.GetValue(process) as ProcessInfo; if (pro != null && pro.IsEnable) { res = KillProcess(pro); if (res != 0) { break; } pro.State = false; // _cache.Set(pro.ProPath, pro); Thread.Sleep(10); } } StopMointor(projectName); if (res == 0) { return new ApiResult(); } return new ApiResult() { Message = "操作失败" }; } private bool CMDStartProcess(ProcessInfo proInfo) { //* Create your Process Process process = new Process(); process.Exited += Process_Exited; process.EnableRaisingEvents = true; process.StartInfo.FileName = Path.GetFullPath(Path.Combine(proInfo.ProPath, proInfo.ProName + ".exe")); process.StartInfo.WorkingDirectory = Path.GetFullPath(proInfo.ProPath); process.StartInfo.Arguments = proInfo.ProParams; Debug.WriteLine($"*******ProcessName:{process.StartInfo.FileName}, arguments:{process.StartInfo.Arguments}*********"); process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; //* Set your output and error (asynchronous) handlers { process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); } //* Start process and handlers bool res = process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); // process.WaitForExit(); return res; } private void Process_Exited(object? sender, EventArgs e) { } void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) { Debug.WriteLine("output*************:{0},{1}", sendingProcess.ToString(), outLine.Data); if (string.IsNullOrEmpty(outLine.Data)) return; if (outLine.Data.Contains("ProcessSlice:")) { var pro = sendingProcess as Process; if (pro != null) { } } else if (outLine.Data.Contains("ML ")) { var pro = sendingProcess as Process; if (pro != null) { var msEvent= new MsEventModel(outLine.Data) { CurrentTime = DateTime.Now }; Console.WriteLine($"processName:{pro.ProcessName},message:{outLine.Data}"); } } } public int StartProcess(ProcessInfo proInfo) { bool res = CMDStartProcess(proInfo); int seInd = res ? 0 : 1; return seInd; } /// /// 结束进程 /// /// /// 0=成功;1=未找到进程;-1=失败 private int KillProcess(ProcessInfo processInfo) { int ri = 0; if (processInfo != null) { if (processInfo.ProName != null) { try { Process[] localByName = Process.GetProcessesByName(processInfo.ProName); if (localByName.Length == 0) { ri = 1; return ri; } foreach (var item in localByName) { item.Kill(); } return ri; } catch (Exception) { return -1; } } else { return 0; } } else { return 0; } } /// /// 查找进程 /// /// /// 0=正在运行;1=未运行;-1=系统错误 private int FindProcess(ProcessInfo processInfo) { int ri = 0; try { Process[] localByName = Process.GetProcessesByName(processInfo.ProName); if (localByName.Length == 0) { ri = 1; return ri; } else { List pro = null; if (processInfo.ProName == "server") { pro = localByName.Where(p => p.MainModule.FileName.Contains(processInfo.ProName)).ToList(); } else { pro = localByName.Where(p => p.MainModule.FileName.Contains(processInfo.ProPath)).ToList(); } if (!pro.Any()) { ri = 1; } return ri; } } catch (Exception) { return -1; } } public string ProcessStatus { get; set; } public ApiResult GetState(string projectName, int id) { ProcessInfo pro = null; if(id==1) { pro = this.RedisServer; } ProjectMonitor.TryGetValue(projectName, out ProcessConfig process); if (process == null || (id < 1|| id > 3)) { return new ApiResult(); } pro = id == 1 ?pro:(id==2)? process.Apms : process.RecvMqtt; int sfp = FindProcess(pro); if (sfp != 0) { return new ApiResult { Code = System.Net.HttpStatusCode.NotFound }; } return new ApiResult { Code = System.Net.HttpStatusCode.OK, Data = new { name = pro.ProName, state = sfp == 0 ? 1 : 0, start_time = pro.StartTime, running_time = (DateTime.Now - pro.StartTime).TotalSeconds, } }; } #endregion public ApiResult ExportCSV(string fileName, List stations) { DataTable dataTable = new DataTable(); string[] header = new string[] { "project_id", "net", "sta"," x2000", "y2000", "z2000", "sens", "begin", "stop", "sitenum" }; DataColumn da = new DataColumn(); foreach (var item in header) { dataTable.Columns.Add(item, typeof(string)); } foreach (var sta in stations) { dataTable.Rows.Add(sta.project_id, sta.network,sta.num,sta.coord_e,sta.coord_n,sta.altitude,sta.sens,sta.begin_time,sta.end_time,sta.site_number); } return ExportExcel(fileName,dataTable, header); } /// 导出csv表格 /// /// 数据集合 /// 数据表头 /// 标题 /// private ApiResult ExportExcel(string fileName, DataTable dt, string[] header, string title = null) { Workbook wb = new Workbook(); try { Worksheet sheet = wb.Worksheets[0]; sheet.Name = "station数据"; if (dt.Rows.Count <= 0) { return new ApiResult() { Code= System.Net.HttpStatusCode.NoContent,Message="没有数据"}; } // 为单元格添加样式 Aspose.Cells.Style style = wb.CreateStyle(); //style.HorizontalAlignment = Aspose.Cells.TextAlignmentType.Center; //设置居中 style.Font.Size = 20;//文字大小 style.Font.IsBold = true;//粗体 style.HorizontalAlignment = TextAlignmentType.Center;//文字居中 // 为合计单元格样式 Aspose.Cells.Style sumstyle = wb.CreateStyle(); sumstyle.Font.Size = 12;//文字大小 sumstyle.Font.IsBold = true;//粗体 sumstyle.Font.Color = System.Drawing.Color.Red; //颜色 //style.HorizontalAlignment = TextAlignmentType.Center;//文字居中 //添加标题 int rowIndex = 0; sheet.Cells.SetRowHeight(rowIndex, 40); //设置行高 if (title != null) { sheet.Cells[rowIndex, 0].PutValue(title); sheet.Cells[rowIndex, 0].SetStyle(style); sheet.Cells.Merge(0, 0, 1, header.Length); //合并行 Merge(1, 1,1, 5); 第一行 第一列 到 第一行 第 5列 //Merge切记后两位参数不能是 0 rowIndex++; } //添加表头 style.Font.Size = 12;//文字大小 sheet.Cells.SetRowHeight(rowIndex, 20); //设置行高 for (int c = 0; c < header.Length; c++) { sheet.Cells[rowIndex, c].PutValue(header[c]); sheet.Cells[rowIndex, c].SetStyle(style); sheet.Cells.SetColumnWidth(c, 20);//设置宽度 } rowIndex++; //添加内容 for (int r = 0; r < dt.Rows.Count; r++)//遍历DataTable行 { for (int c = 0; c < header.Length; c++) //列只遍历到和表头数量相等的列,其余的列不导出 { //自动把数字变量转出后 单元格变为数字类型。 try { //把添加变量转字符类型存储 sheet.Cells[r + rowIndex, c].PutValue(dt.Rows[r][c].ToString()); // sheet.Cells[r + rowIndex, c].PutValue(Convert.ToDecimal(dt.Rows[r][c])); //要导出数字列是数字类型,必须把添加变量转数字类型。 } catch { //把添加变量转字符类型存储 sheet.Cells[r + rowIndex, c].PutValue(dt.Rows[r][c].ToString()); } } } //输出到Excel wb.Save(fileName, new OoxmlSaveOptions(SaveFormat.Csv)); //保存成97或2003写法 //workbook.Save(“output.xls, New XlsSaveOptions(SaveFormat.Excel97To2003)) // 释放Excel对象 sheet.Dispose(); wb.Dispose(); } catch (Exception e) { return new ApiResult() { Code = System.Net.HttpStatusCode.NoContent, Message = $"保存{fileName}文件异常:{e.Message}" }; } return new ApiResult(); } } }