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.

499 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()
{
ProPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CommonData.RedisDefaultPath),
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)
{
int sfServer = FindProcess(RedisServer);
RedisServer.State = sfServer == 0 ? true : false;
var messageRerver = new
{
projectName = item.Key,
ProName = RedisServer.ProName,
RunState = RedisServer.State ? 1 :2,
RunTime = (DateTime.Now - RedisServer.StartTime).TotalSeconds,
};
_redisList.Publish(CommonData.RedisPublish, Newtonsoft.Json.JsonConvert.SerializeObject(messageRerver));
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,
//0已停止1正常启动2启动失败
RunState = sfp == 0 ? 1 : 2,
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,
//0已停止1正常启动2启动失败
RunState = 0,
RunTime = 0,
}));
}
}
}
}
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;
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();
}
}
}