using DBModel; using DBNames; using log4net; using SCADA.CommonLib; using SCADA.CommonLib.Helper; using SCADA_DAQ.Plugin.Core; using SCADA_DAQ.Plugin.Core.License; using SCADA_DAQ.Plugin.CoreUI; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; namespace SCADA_DAQ { internal class SystemControl { /// /// /// bool isShutDown = false; ILog Log { get; set; } = null; private EventWaitHandle evh; public App App { get; private set; } private static SystemControl systemControl; private static readonly object syncObj = new object(); private readonly List Timers = new List(); private readonly Task initTask; private readonly Task initServer; private ServiceHost host = null; public string UidVersion { get; } private string SoftWareId { get; set; } private SystemControl(App app) { App = app; PowerOnTime = DateTime.Now; SoftWareId = MD5Helper.GetFileMD5(GetType().Assembly.Location); UidVersion = $"{ApplicationHelper.GetAppVersion()}.{Convert.ToUInt16(SoftWareId.Substring(0, 3), 16):D4}"; app.UidVersion = UidVersion; initTask = Task.Factory.StartNew(() => { bool createdNew = true; if (Env.SingleModel.Value == true) { evh = new EventWaitHandle(false, EventResetMode.AutoReset, App.ProductId, out createdNew); var currentProcess = Process.GetCurrentProcess(); var ps = Process.GetProcessesByName( Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().ManifestModule.Name)) .Where(t => t.Id != currentProcess.Id); if (createdNew) //信号锁创建成功,且是单例模式 { foreach (Process p in ps) { p.Kill(); } } else { if (ps.Count() == 1 && ps.First().MainWindowHandle != IntPtr.Zero) { evh?.Set(); app.Dispatcher.Invoke(new Action(() => { isShutDown = true; App.Shutdown(1); })); return; } else { foreach (Process p in ps) //单例模式下如果主界面没有出现,或者有多个进程,直接全部kill掉 { p.Kill(); } } } } Console.WriteLine($"开始获取电脑ID {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"); LicenseManage.GenerateID(App.ProductId, out var str); Console.WriteLine($"检查释放系统组件 {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}"); ReleaseRunTime(); try { var dtClass = DataTableHelper.DtToList(Env.DAL.App_Classes.GetData($"{T_Col_Name.App_Classes.ClassType_Int}=2")); if (dtClass != null) { Env.Schedual.Classes.Clear(); foreach (var appClassese in dtClass) { var startTime = TimeSpan.Parse(appClassese.StartTime_Str); var endTime = TimeSpan.Parse(appClassese.EndTime_Str); Env.Schedual.Classes.Add(new WorkShift(startTime, endTime, appClassese.ClassesName_Str)); } } } catch (Exception) { Env.Schedual.Classes.Add(new WorkShift(new TimeSpan(7, 30, 0), new TimeSpan(19, 30, 0), "白班")); Env.Schedual.Classes.Add(new WorkShift(new TimeSpan(19, 30, 0), new TimeSpan(7, 30, 0), "夜班")); } Plugin.CoreUI.SystemApp.SystemStatictics.AppStart(); CreateBackGroundTask(ReportOnLine, 10 * 1000 * 60, 10 * 1000, true, "ReportAppInfo"); CreateBackGroundTask(Plugin.CoreUI.SystemApp.SystemStatictics.UpdateLastOnLineTime, 1 * 1000 * 60, 10 * 1000, true, "UpdateLastTime"); CreateBackGroundTask(Plugin.CoreUI.SystemApp.SystemStatictics.StatisticsRunTime, 30 * 1000, 15 * 1000, true, "StatisticsRunTime"); }); initServer = Task.Factory.StartNew(() => { }); } private DateTime PowerOnTime { get; set; } public static SystemControl Create(App app) { lock (syncObj) { if (systemControl == null) { systemControl = new SystemControl(app); } } return systemControl; } public static SystemControl GetInstance() { return systemControl; } public void SystemInit() { App.DispatcherUnhandledException += Application_DispatcherUnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; Task.Factory.StartNew(() => { Task.WaitAll(initTask); if (isShutDown) return; var st = new System.Diagnostics.Stopwatch(); st.Start(); host = ServiceHost.Instance; host.Start(); (App as IApp).ServiceHost = host; try { Env.StartTime = DateTime.Now; Log = SCADA.CommonLib.LoggerHelper.Logger.CreatLogger(typeof(App)); Dictionary logLevel = new Dictionary() { { SCADA.CommonLib.LoggerHelper.LogLevel.All,log4net.Core.Level.All}, { SCADA.CommonLib.LoggerHelper.LogLevel.Debug,log4net.Core.Level.Debug}, { SCADA.CommonLib.LoggerHelper.LogLevel.Info,log4net.Core.Level.Info}, { SCADA.CommonLib.LoggerHelper.LogLevel.Warn,log4net.Core.Level.Warn}, { SCADA.CommonLib.LoggerHelper.LogLevel.Error,log4net.Core.Level.Error}, { SCADA.CommonLib.LoggerHelper.LogLevel.Fatal,log4net.Core.Level.Fatal}, { SCADA.CommonLib.LoggerHelper.LogLevel.None,log4net.Core.Level.Off}, }; LogManager.GetRepository().Threshold = logLevel[Env.LogLevel.Value]; Log.Info($"App {App.ProductId} ({UidVersion}) is starting ……"); Task.WaitAll(initServer); Console.WriteLine($"系统初始化完成 {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}"); Func action = null; LoadLicense(); App.Dispatcher.Invoke(new Action(() => { if (App.MainWindow is MainWindow window) { action = window.GetLicense; } })); if (!LicenseManage.CheckID(App.ProductId, out var str, action)) { App.Dispatcher.Invoke(new Action(() => { isShutDown = true; App.Shutdown(100); })); return; } else { Env.LicenseInfo = LicenseManage.GetLicenseInfo(App.ProductId); } Env.ComputerId.Value = Env.LicenseInfo.Computer.ComputerId; App.Dispatcher.Invoke(new Action(() => { if (App.MainWindow is MainWindow window) { window.LicenseInfo = Env.LicenseInfo; Log.Debug($"系统初始化完成,即将开启"); window.SystemInited(); Env.SetTheme(); Env.SetLanguage(); Env.SetFont(); } })); } catch (Exception ex) { FalatReport(ex); Log.Error(ex); } new Thread(() => { while (!isShutDown && evh != null) { if (evh.WaitOne(-1)) { if (isShutDown) { return; } App.Dispatcher.Invoke(new Action(() => { App.MainWindow.Topmost = true; App.MainWindow.WindowState = WindowState.Maximized; App.MainWindow.Topmost = false; })); } } }).Start(); }); } /// /// 重新加载授权文件 /// internal void LoadLicense() { Env.LicenseInfo = LicenseManage.GetLicenseInfo(App.ProductId); if (isShutDown) return; App.Dispatcher.Invoke(new Action(() => { if (App.MainWindow is MainWindow window) { window.MainWindowViewModel.CopyRightInfo = $"{Env.AuthorInfo.Value}({Env.LicenseInfo.LicenseType})"; } })); ReportAppInfo(true); } private DateTime lastReportSuccessTime = DateTime.MinValue; private void ReportOnLine() { if ((DateTime.Now - lastReportSuccessTime).TotalSeconds > 590) { ReportAppInfo(true); } } private void ReportAppInfo(bool isOnline = true) { if (EicpCoreManage.ReportAppInfo(new { SessionID = App.SessionId, AppName = Env.LicenseInfo?.AppName, Version = UidVersion, CustomerTag = Env.ComputerTag.Value, ComputerId = Env.LicenseInfo?.Computer.ComputerId, LicenseId = Env.LicenseInfo?.LicenseId, LicenseType = Env.LicenseInfo?.LicenseType.ToString(), ActiveTime = Env.LicenseInfo?.ActiveTime, ExpireDate = Env.LicenseInfo?.ActiveTime.AddDays(Env.LicenseInfo.ExpireDays), TotalOutputPcs = Env.TotalOutputPcs.Value, TotalOutputQty = Env.TotalOutputQty.Value, IsOnline = isOnline }, out var appName)) { lastReportSuccessTime = DateTime.Now; Env.ComputerTag.Value = appName; } } private void FalatReport(Exception exception) { try { EicpCoreManage.FalatReport(new { SessionID = App.SessionId, AppName = Env.LicenseInfo?.AppName, Version = UidVersion, ComputerId = Env.LicenseInfo?.Computer?.ComputerId, SoftwareID = SoftWareId, Customer = System.Windows.Forms.Application.CompanyName, Message = exception.Message, PowerOnTime = PowerOnTime, RunTime = DateTime.Now - PowerOnTime, Exception = exception?.ToString() }); } catch (Exception ex) { Log?.Error(ex); } //Task.Factory.StartNew(() => //{ // //var webApi = new WebApiHelper($"http://localhost:4082/AppManage/AppFatalReport"); // var webApi = new WebApiHelper($"http://{Env.WebServerAddress.Value}/AppManage/AppFatalReport"); // var res = webApi.POST(); //}); } public bool RestartHost() { return host.Restart(); } private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { Log?.Error(e.Exception); e.Handled = true; FalatReport(e.Exception); } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { FalatReport(e.ExceptionObject as Exception); Log?.Fatal(e.ExceptionObject); LogManager.Flush(10); ExitHandler(e.ExceptionObject.ToString()); App?.Dispatcher.BeginInvoke(new Action(() => { MessageBox.Show(e.ExceptionObject.ToString()); })); } /// /// 释放运行时压缩包 /// private void ReleaseRunTime() { var runTimeLibDic = new Dictionary() { {"Content.zip","Content" }, {"HCNETSDKLib.zip",null }, {"RunTime.zip",null }, {"SyntecLib_v4.zip",null}, //{"FocasLib.zip",AppDomain.CurrentDomain.BaseDirectory }, {"x86_x64.zip",null }, }; foreach (var item in runTimeLibDic) { try { if (System.IO.File.Exists(item.Key)) { ZipHelper.UnZip(item.Key, item.Value); FileHelper.DeleteFile(item.Key); } } catch (Exception ex) { Log.Error(ex); } } } private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { Log.Fatal(e.Exception); FalatReport(e.Exception); //App?.Dispatcher.BeginInvoke( // new Action( // () => // { // MessageBox.Show("程序出现异常(task):" + e.Exception.ToString()); // })); ExitHandler(e.Exception.Message); } private void ExitHandler(string exitMsg) { Plugin.CoreUI.SystemApp.SystemStatictics.AppExit(exitMsg); ReportAppInfo(false); } public void ApplicationExit(int exitCode) { isShutDown = true; evh?.Set(); evh?.Dispose(); } public void ApplicationDispose(int exitCode) { if (host != null) host.Stop(); foreach (var item in Timers) { item.Dispose(); } var exitReason = ""; if (ExitCode.ContainsKey(exitCode)) { exitReason = ExitCode[exitCode]; } ExitHandler(exitReason); if (Log != null) { Log.Info($"{App.ProductId}({UidVersion}) is shutdown by {exitReason}"); SCADA.CommonLib.LoggerHelper.Logger.Dispose(); } } public void ApplicationSessionEnding(object sender, SessionEndingCancelEventArgs e) { Log.Error($"计算机已注销或关闭,原因:{e.ReasonSessionEnding}"); } /// /// 创建一个后台任务 /// /// /// 重复执行间隔 毫秒 /// 延迟时间 /// 当转到后台时继续执行 /// public void CreateBackGroundTask(ThreadStart task, int cycleTime, int delayTime = 0, bool backgroundContinue = false, string taskName = null) { Timers.Add(new AdvanceTimer(task, taskName, cycleTime, delayTime) { IsBackground = backgroundContinue, IsActived = true, TimerName = taskName }); } private readonly Dictionary ExitCode = new Dictionary() { {0,"User Exit"}, {100,"invalid license"}, }; } }