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"},
};
}
}