SystemControl.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. using DBModel;
  2. using DBNames;
  3. using log4net;
  4. using SCADA.CommonLib;
  5. using SCADA.CommonLib.Helper;
  6. using SCADA.CommonLib.License;
  7. using SCADA_DAQ.Plugin.Core;
  8. using SCADA_DAQ.Plugin.Core.License;
  9. using SCADA_DAQ.Plugin.CoreUI;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Diagnostics;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Reflection;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. using System.Windows;
  19. namespace SCADA_DAQ
  20. {
  21. internal class SystemControl
  22. {
  23. /// <summary>
  24. ///
  25. /// </summary>
  26. bool isShutDown = false;
  27. ILog Log { get; set; } = null;
  28. private EventWaitHandle evh;
  29. public App App { get; private set; }
  30. private static SystemControl systemControl;
  31. private static readonly object syncObj = new object();
  32. private readonly List<AdvanceTimer> Timers = new List<AdvanceTimer>();
  33. private readonly Task initTask;
  34. private readonly Task initServer;
  35. private ServiceHost host = null;
  36. public string UidVersion { get; }
  37. private string SoftWareId { get; set; }
  38. private SystemControl(App app)
  39. {
  40. App = app;
  41. PowerOnTime = DateTime.Now;
  42. SoftWareId = MD5Helper.GetFileMD5(GetType().Assembly.Location);
  43. UidVersion = $"{ApplicationHelper.GetAppVersion()}.{Convert.ToUInt16(SoftWareId.Substring(0, 3), 16):D4}";
  44. app.RuntimeInfo.UidVersion = UidVersion;
  45. initTask = Task.Factory.StartNew(() =>
  46. {
  47. bool createdNew = true;
  48. if (app.SystemConfig.SingleModel == true)
  49. {
  50. evh = new EventWaitHandle(false, EventResetMode.AutoReset, App.RuntimeInfo.ProductId, out createdNew);
  51. var currentProcess = Process.GetCurrentProcess();
  52. var ps = Process.GetProcessesByName(
  53. Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().ManifestModule.Name))
  54. .Where(t => t.Id != currentProcess.Id);
  55. if (createdNew) //信号锁创建成功,且是单例模式
  56. {
  57. foreach (Process p in ps)
  58. {
  59. p.Kill();
  60. }
  61. }
  62. else
  63. {
  64. if (ps.Count() == 1 && ps.First().MainWindowHandle != IntPtr.Zero)
  65. {
  66. evh?.Set();
  67. app.Dispatcher.Invoke(new Action(() =>
  68. {
  69. isShutDown = true;
  70. App.Shutdown(1);
  71. }));
  72. return;
  73. }
  74. else
  75. {
  76. foreach (Process p in ps) //单例模式下如果主界面没有出现,或者有多个进程,直接全部kill掉
  77. {
  78. p.Kill();
  79. }
  80. }
  81. }
  82. }
  83. Console.WriteLine($"开始获取电脑ID {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
  84. LicenseManage.GenerateID(App.RuntimeInfo.ProductId, out var str);
  85. Console.WriteLine($"检查释放系统组件 {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
  86. ReleaseRunTime();
  87. try
  88. {
  89. var dtClass = DataTableHelper.DtToList<App_Classes>(Env.DAL.App_Classes.GetData($"{T_Col_Name.App_Classes.ClassType_Int}=2"));
  90. if (dtClass != null)
  91. {
  92. Env.Schedual.Classes.Clear();
  93. foreach (var appClassese in dtClass)
  94. {
  95. var startTime = TimeSpan.Parse(appClassese.StartTime_Str);
  96. var endTime = TimeSpan.Parse(appClassese.EndTime_Str);
  97. Env.Schedual.Classes.Add(new WorkShift(startTime,
  98. endTime, appClassese.ClassesName_Str));
  99. }
  100. }
  101. }
  102. catch (Exception)
  103. {
  104. Env.Schedual.Classes.Add(new WorkShift(new TimeSpan(7, 30, 0), new TimeSpan(19, 30, 0), "白班"));
  105. Env.Schedual.Classes.Add(new WorkShift(new TimeSpan(19, 30, 0), new TimeSpan(7, 30, 0), "夜班"));
  106. }
  107. CreateBackGroundTask(ReportOnLine, 10 * 1000 * 60, 10 * 1000, true, "ReportAppInfo");
  108. var systemStatics = Plugin.CoreUI.SystemApp.SystemStatictics.Create();
  109. systemStatics.AppRuntime = App;
  110. systemStatics.Start();
  111. });
  112. initServer = Task.Factory.StartNew(() =>
  113. {
  114. });
  115. }
  116. private DateTime PowerOnTime { get; set; }
  117. public static SystemControl Create(App app)
  118. {
  119. lock (syncObj)
  120. {
  121. if (systemControl == null)
  122. {
  123. systemControl = new SystemControl(app);
  124. }
  125. }
  126. return systemControl;
  127. }
  128. public static SystemControl GetInstance()
  129. {
  130. return systemControl;
  131. }
  132. public void SystemInit()
  133. {
  134. App.DispatcherUnhandledException += Application_DispatcherUnhandledException;
  135. AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
  136. TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
  137. Task.Factory.StartNew(() =>
  138. {
  139. Task.WaitAll(initTask);
  140. if (isShutDown) return;
  141. var st = new Stopwatch();
  142. st.Start();
  143. EicpCoreManage.AppRuntime = App;
  144. host = ServiceHost.Instance;
  145. (App as IApp).ServiceHost = host;
  146. host.Start(App);
  147. try
  148. {
  149. App.RuntimeInfo.StartTime = DateTime.Now;
  150. Log = SCADA.CommonLib.LoggerHelper.Logger.CreateLogger(typeof(App));
  151. Dictionary<SCADA.CommonLib.LoggerHelper.LogLevel, log4net.Core.Level> logLevel =
  152. new Dictionary<SCADA.CommonLib.LoggerHelper.LogLevel, log4net.Core.Level>()
  153. {
  154. { SCADA.CommonLib.LoggerHelper.LogLevel.All,log4net.Core.Level.All},
  155. { SCADA.CommonLib.LoggerHelper.LogLevel.Debug,log4net.Core.Level.Debug},
  156. { SCADA.CommonLib.LoggerHelper.LogLevel.Info,log4net.Core.Level.Info},
  157. { SCADA.CommonLib.LoggerHelper.LogLevel.Warn,log4net.Core.Level.Warn},
  158. { SCADA.CommonLib.LoggerHelper.LogLevel.Error,log4net.Core.Level.Error},
  159. { SCADA.CommonLib.LoggerHelper.LogLevel.Fatal,log4net.Core.Level.Fatal},
  160. { SCADA.CommonLib.LoggerHelper.LogLevel.None,log4net.Core.Level.Off},
  161. };
  162. LogManager.GetRepository().Threshold = logLevel[App.SystemConfig.LogLevel];
  163. Log.Info($"App {App.RuntimeInfo.ProductId} ({UidVersion}) is starting ……");
  164. Task.WaitAll(initServer);
  165. Console.WriteLine($"系统初始化完成 {DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}");
  166. Func<bool> action = null;
  167. LoadLicense();
  168. //App.Dispatcher.Invoke(new Action(() =>
  169. //{
  170. // if (App.MainWindow is MainWindow window)
  171. // {
  172. // action = window.GetLicense;
  173. // }
  174. //}));
  175. //if (!LicenseManage.CheckID(App as IApp, out var str, action))
  176. //{
  177. // App.Dispatcher.Invoke(new Action(() =>
  178. // {
  179. // isShutDown = true;
  180. // App.Shutdown(100);
  181. // }));
  182. // return;
  183. //}
  184. //else
  185. //{
  186. // App.RuntimeInfo.LicenseInfo = LicenseManage.GetLicenseInfo(App.RuntimeInfo.ProductId);
  187. //}
  188. App.RuntimeInfo.ComputerId = App.RuntimeInfo.LicenseInfo.Computer.ComputerId;
  189. App.RuntimeInfo.LicenseInfo.LicenseType = LicenseType.Permanentlicense;
  190. App.Dispatcher.Invoke(new Action(() =>
  191. {
  192. if (App.MainWindow is MainWindow window)
  193. {
  194. window.LicenseInfo = App.RuntimeInfo.LicenseInfo;
  195. Log.Debug($"系统初始化完成,即将开启");
  196. Env.SetLanguage();
  197. window.SystemInited();
  198. Env.SetTheme();
  199. Env.SetFont();
  200. }
  201. }));
  202. }
  203. catch (Exception ex)
  204. {
  205. FalatReport(ex);
  206. Log.Error(ex);
  207. }
  208. new Thread(() =>
  209. {
  210. while (!isShutDown && evh != null)
  211. {
  212. if (evh.WaitOne(-1))
  213. {
  214. if (isShutDown)
  215. {
  216. return;
  217. }
  218. App.Dispatcher.Invoke(new Action(() =>
  219. {
  220. App.MainWindow.Topmost = true;
  221. App.MainWindow.WindowState = WindowState.Maximized;
  222. App.MainWindow.Topmost = false;
  223. }));
  224. }
  225. }
  226. }).Start();
  227. });
  228. }
  229. /// <summary>
  230. /// 重新加载授权文件
  231. /// </summary>
  232. internal void LoadLicense()
  233. {
  234. App.RuntimeInfo.LicenseInfo = LicenseManage.GetLicenseInfo(App.RuntimeInfo.ProductId);
  235. if (isShutDown || App.RuntimeInfo.LicenseInfo == null) return;
  236. if (!App.Dispatcher.HasShutdownStarted)
  237. {
  238. App.Dispatcher.Invoke(new Action(() =>
  239. {
  240. if (App.MainWindow is MainWindow window)
  241. {
  242. window.MainWindowViewModel.CopyRightInfo = $"{App.SystemConfig.AuthorInfo}({App.RuntimeInfo.LicenseInfo.LicenseType})";
  243. }
  244. }));
  245. ReportAppInfo(true);
  246. }
  247. }
  248. private DateTime lastReportSuccessTime = DateTime.MinValue;
  249. private void ReportOnLine()
  250. {
  251. if ((DateTime.Now - lastReportSuccessTime).TotalSeconds > 590)
  252. {
  253. ReportAppInfo(true);
  254. }
  255. }
  256. private void ReportAppInfo(bool isOnline = true)
  257. {
  258. if (App.RuntimeInfo.LicenseInfo != null && (App.RuntimeInfo.LicenseInfo.LicenseType == LicenseType.TempLicense || App.RuntimeInfo.LicenseInfo.LicenseType == LicenseType.Permanentlicense))
  259. {
  260. var reportInfo = new
  261. {
  262. SessionID = App.RuntimeInfo.SessionId,
  263. AppName = App.RuntimeInfo.LicenseInfo?.AppName,
  264. Version = UidVersion,
  265. CustomerTag = App.SystemConfig.ComputerTag,
  266. ComputerId = App.RuntimeInfo.LicenseInfo?.Computer.ComputerId,
  267. LicenseId = App.RuntimeInfo.LicenseInfo?.LicenseId,
  268. LicenseType = App.RuntimeInfo.LicenseInfo?.LicenseType.ToString(),
  269. ActiveTime = App.RuntimeInfo.LicenseInfo?.ActiveTime,
  270. ExpireDate = App.RuntimeInfo.LicenseInfo?.ActiveTime.AddDays(App.RuntimeInfo.LicenseInfo.ExpireDays),
  271. TotalOutputPcs = Env.TotalOutputPcs.Value,
  272. TotalOutputQty = Env.TotalOutputQty.Value,
  273. IsOnline = isOnline
  274. };
  275. if (EicpCoreManage.ReportAppInfo(reportInfo, out var appName))
  276. {
  277. lastReportSuccessTime = DateTime.Now;
  278. App.SystemConfig.ComputerTag = appName;
  279. }
  280. }
  281. }
  282. private void FalatReport(Exception exception)
  283. {
  284. if (isShutDown) return;
  285. if (App.RuntimeInfo.LicenseInfo != null &&
  286. (App.RuntimeInfo.LicenseInfo.LicenseType == LicenseType.TempLicense ||
  287. App.RuntimeInfo.LicenseInfo.LicenseType == LicenseType.Permanentlicense))
  288. {
  289. try
  290. {
  291. EicpCoreManage.FalatReport(new
  292. {
  293. SessionID = App.RuntimeInfo.SessionId,
  294. AppName = App.RuntimeInfo.LicenseInfo?.AppName,
  295. Version = UidVersion,
  296. ComputerId = App.RuntimeInfo.LicenseInfo?.Computer?.ComputerId,
  297. SoftwareID = SoftWareId,
  298. Customer = System.Windows.Forms.Application.CompanyName,
  299. Message = exception.Message,
  300. PowerOnTime = PowerOnTime,
  301. RunTime = DateTime.Now - PowerOnTime,
  302. Exception = exception?.ToString()
  303. });
  304. }
  305. catch (Exception ex)
  306. {
  307. Log?.Error(ex);
  308. }
  309. }
  310. }
  311. public bool RestartHost()
  312. {
  313. return host.Restart();
  314. }
  315. private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
  316. {
  317. Log?.Error(e.Exception);
  318. e.Handled = true;
  319. if (!isShutDown)
  320. {
  321. FalatReport(e.Exception);
  322. }
  323. }
  324. private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  325. {
  326. FalatReport(e.ExceptionObject as Exception);
  327. Log?.Fatal(e.ExceptionObject);
  328. LogManager.Flush(10);
  329. ExitHandler(e.ExceptionObject.ToString());
  330. App?.Dispatcher.BeginInvoke(new Action(() =>
  331. {
  332. MessageBox.Show(e.ExceptionObject.ToString());
  333. }));
  334. }
  335. /// <summary>
  336. /// 释放运行时压缩包
  337. /// </summary>
  338. private void ReleaseRunTime()
  339. {
  340. var runTimeLibDic = new Dictionary<string, string>()
  341. {
  342. {"Content.zip","Content" },
  343. {"EicpWeb.zip","Content" },
  344. {"EicpCustomer.zip","Content" },
  345. {"HCNETSDKLib.zip",null },
  346. {"RunTime.zip",null },
  347. {"SyntecLib_v4.zip",null},
  348. {"FocasLib.zip",AppDomain.CurrentDomain.BaseDirectory },
  349. {"DeviceCfg.zip",null},
  350. {"x86_x64.zip",null },
  351. };
  352. foreach (var item in runTimeLibDic)
  353. {
  354. try
  355. {
  356. if (System.IO.File.Exists(item.Key))
  357. {
  358. ZipHelper.UnZip(item.Key, item.Value);
  359. FileHelper.DeleteFile(item.Key);
  360. }
  361. }
  362. catch (Exception ex)
  363. {
  364. Log.Error(ex);
  365. }
  366. }
  367. }
  368. private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
  369. {
  370. Log?.Fatal(e.Exception);
  371. FalatReport(e.Exception);
  372. ExitHandler(e.Exception.Message);
  373. }
  374. private void ExitHandler(string exitMsg)
  375. {
  376. Plugin.CoreUI.SystemApp.SystemStatictics.Create().AppExit(exitMsg);
  377. ReportAppInfo(false);
  378. }
  379. public void ApplicationExit(int exitCode)
  380. {
  381. isShutDown = true;
  382. evh?.Set();
  383. evh?.Dispose();
  384. }
  385. public void ApplicationDispose(int exitCode)
  386. {
  387. isShutDown = true;
  388. if (host != null) host.Stop();
  389. foreach (var item in Timers)
  390. {
  391. item.Dispose();
  392. }
  393. var exitReason = "";
  394. if (ExitCode.ContainsKey(exitCode))
  395. {
  396. exitReason = ExitCode[exitCode];
  397. }
  398. ExitHandler(exitReason);
  399. if (Log != null)
  400. {
  401. Log.Info($"{App.RuntimeInfo.ProductId}({UidVersion}) is shutdown by {exitReason}");
  402. SCADA.CommonLib.LoggerHelper.Logger.Dispose();
  403. }
  404. }
  405. public void ApplicationSessionEnding(object sender, SessionEndingCancelEventArgs e)
  406. {
  407. Log.Error($"计算机已注销或关闭,原因:{e.ReasonSessionEnding}");
  408. }
  409. /// <summary>
  410. /// 创建一个后台任务
  411. /// </summary>
  412. /// <param name="task"></param>
  413. /// <param name="cycleTime">重复执行间隔 毫秒</param>
  414. /// <param name="delayTime">延迟时间</param>
  415. /// <param name="backgroundContinue">当转到后台时继续执行</param>
  416. /// <param name="taskName"></param>
  417. public void CreateBackGroundTask(ThreadStart task, int cycleTime, int delayTime = 0, bool backgroundContinue = false, string taskName = null)
  418. {
  419. Timers.Add(new AdvanceTimer(task, taskName, cycleTime, delayTime)
  420. {
  421. IsBackground = backgroundContinue,
  422. IsActived = true,
  423. TimerName = taskName
  424. });
  425. }
  426. private readonly Dictionary<int, string> ExitCode = new Dictionary<int, string>()
  427. {
  428. {0,"User Exit"},
  429. {100,"invalid license"},
  430. };
  431. }
  432. }