You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

500 lines
19 KiB
C#

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<string, ProcessConfig> ProjectMonitor = new ConcurrentDictionary<string, ProcessConfig>();
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)
{
var path= Path.GetDirectoryName(e.FullPath);
var dir = new DirectoryInfo(path);
var files= dir.GetFiles("*.json");
string name = $"HA.{msEvent.OriginTime.Year}{msEvent.OriginTime.Month:D2}{msEvent.OriginTime.Day:D2}T{msEvent.OriginTime.Hour:D2}{msEvent.OriginTime.Minute:D2}{msEvent.OriginTime.Second:D2}";
string jsonStr = string.Empty;
foreach (var item in files)
{
if (item.FullName.Contains(name))
{
jsonStr= File.ReadAllText(item.FullName);
break;
}
}
_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,
json_str= jsonStr,
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 = 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;
}
/// <summary>
/// 结束进程
/// </summary>
/// <param name="processInfo"></param>
/// <returns>0=成功;1=未找到进程;-1=失败</returns>
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;
}
}
/// <summary>
/// 查找进程
/// </summary>
/// <param name="processInfo"></param>
/// <returns>0=正在运行;1=未运行;-1=系统错误</returns>
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<Process> 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<StationDTO> 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表格
/// </summary>
/// <param name="list">数据集合</param>
/// <param name="header">数据表头</param>
/// <param name=" title"> 标题</param>
/// <returns></returns>
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();
}
}
}