ServiceHost.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using LocalDB.DBModel;
  2. using LocalDB.DBNames;
  3. using log4net;
  4. using SCADA.CommonLib;
  5. using SCADA.CommonLib.Data.DIL;
  6. using SCADA.CommonLib.Helper;
  7. using SCADA.CommonLib.Service;
  8. using System;
  9. using System.Collections.Concurrent;
  10. using System.Collections.Generic;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Reflection;
  14. using System.Threading.Tasks;
  15. namespace SCADA_DAQ
  16. {
  17. /// <summary>
  18. ///
  19. /// </summary>
  20. public class ServiceHost : IServiceHost
  21. {
  22. /// <summary>
  23. ///
  24. /// </summary>
  25. readonly ILog log = SCADA.CommonLib.LoggerHelper.Logger.CreatLogger(typeof(ServiceHost));
  26. /// <summary>
  27. ///
  28. /// </summary>
  29. public ConcurrentDictionary<string, IService> ServiceCollection { get; private set; } = new ConcurrentDictionary<string, IService>();
  30. /// <summary>
  31. ///
  32. /// </summary>
  33. /// <typeparam name="T"></typeparam>
  34. /// <param name="serviceName"></param>
  35. /// <returns></returns>
  36. public T GetService<T>(string serviceName) where T : IService
  37. {
  38. if (ServiceCollection.ContainsKey(serviceName))
  39. {
  40. return (T)ServiceCollection[serviceName];
  41. }
  42. return default;
  43. }
  44. /// <summary>
  45. ///
  46. /// </summary>
  47. /// <typeparam name="T"></typeparam>
  48. /// <returns></returns>
  49. public T GetService<T>() where T : IService
  50. {
  51. return ServiceCollection.Values.OfType<T>().FirstOrDefault();
  52. }
  53. bool isDisposed = false;
  54. private ServiceHost()
  55. {
  56. }
  57. private static ServiceHost _instance;
  58. /// <summary>
  59. ///
  60. /// </summary>
  61. public static ServiceHost Instance { get => _instance ?? (_instance = new ServiceHost()); private set { _instance = value; } }
  62. private ITable serviceTable { get; set; }
  63. /// <summary>
  64. ///
  65. /// </summary>
  66. /// <returns></returns>
  67. public bool Start()
  68. {
  69. try
  70. {
  71. RpcService.GetInstance().Regiseter(this);
  72. var serviceTasks = new List<Task>() { };
  73. serviceTable = GlobalEnv.Instance.LocalAppDB?.GetValueByPath("Sys_Service", true) as ITable;
  74. var services = DataTableHelper.DtToList<Sys_Service>(serviceTable.GetData())?.OrderBy(t => t.StartSquence_Int);
  75. var serviceTypes = PlugInServer.Instance.GetTypes<IService>(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", ""))).ToDictionary(t => t.FullName, t => t);
  76. var updateItems = new ConcurrentBag<Tuple<SelectFilterItem[], UpdateItem[]>>();
  77. if (services == null) return false;
  78. foreach (var item in services)
  79. {
  80. if (item.IsEnable_Bit)
  81. {
  82. var exMsg = "";
  83. var serviceState = "";
  84. var startTime = DateTime.Now;
  85. if (serviceTypes.ContainsKey(item.ServiceType_Str))
  86. {
  87. var task = Task.Factory.StartNew(() =>
  88. {
  89. System.Diagnostics.Stopwatch st = null;
  90. try
  91. {
  92. System.Threading.Thread.Sleep(item.StartDelay_Int);
  93. log.Debug($"服务ID:{item.ID} ,类型:{item.ServiceType_Str} 开始启动");
  94. st = new System.Diagnostics.Stopwatch();
  95. st.Start();
  96. var type = serviceTypes[item.ServiceType_Str];
  97. var constructorInfoArray = type.GetConstructors(BindingFlags.Instance
  98. | BindingFlags.NonPublic
  99. | BindingFlags.Public);
  100. ConstructorInfo noParameterConstructorInfo = null;
  101. foreach (ConstructorInfo constructorInfo in constructorInfoArray)
  102. {
  103. ParameterInfo[] parameterInfoArray = constructorInfo.GetParameters();
  104. if (0 == parameterInfoArray.Length)
  105. {
  106. noParameterConstructorInfo = constructorInfo;
  107. break;
  108. }
  109. }
  110. if (null == noParameterConstructorInfo)
  111. {
  112. throw new NotSupportedException($"Service {item.ServiceType_Str} 没有默认构造函数");
  113. }
  114. var service = (IService)noParameterConstructorInfo.Invoke(null);
  115. if (service.ConfigType != null)
  116. {
  117. service.ServiceConfig = (ObservableObject)JsonHelper.JsonDeserialize(item.ServiceConfig_Str, service.ConfigType) ??
  118. (ObservableObject)Activator.CreateInstance(service.ConfigType);
  119. }
  120. service.ServiceId = item.ID.ToString();
  121. service.ServiceName = item.ServiceName_Str;
  122. service.Start();
  123. startTime = DateTime.Now;
  124. serviceState = "启动成功";
  125. ServiceCollection.TryAdd(service.ServiceName, service);
  126. st.Stop();
  127. log.Debug($"服务ID:{item.ID},名称:{item.ServiceName_Str},类型:{item.ServiceType_Str} 启动成功,耗时:{st.Elapsed}");
  128. }
  129. catch (Exception ex)
  130. {
  131. log.Warn($"服务ID:{item.ID},名称:{item.ServiceName_Str},类型:{item.ServiceType_Str} 启动失败:{ex.Message}");
  132. startTime = DateTime.Now;
  133. log.Error(ex);
  134. exMsg = ex.ToString();
  135. }
  136. finally
  137. {
  138. st?.Stop();
  139. }
  140. });
  141. serviceTasks.Add(task);
  142. task.Wait();
  143. }
  144. else
  145. {
  146. exMsg = $"没有找到 {item.ServiceName_Str}:{item.ServiceType_Str}";
  147. log.Warn(exMsg);
  148. }
  149. if (!string.IsNullOrEmpty(exMsg))
  150. {
  151. serviceState = "启动失败";
  152. }
  153. updateItems.Add(new Tuple<SelectFilterItem[], UpdateItem[]>(
  154. new SelectFilterItem[] { new SelectFilterItem(T_Col_Name.Sys_Service.ID, item.ID) },
  155. new UpdateItem[] {
  156. new UpdateItem(T_Col_Name.Sys_Service.ServiceState_Str, serviceState),
  157. new UpdateItem(T_Col_Name.Sys_Service.StartTime_Dt, startTime),
  158. new UpdateItem(T_Col_Name.Sys_Service.ServiceMessage_Str, exMsg)}
  159. ));
  160. }
  161. }
  162. Task.WaitAll(serviceTasks.ToArray());
  163. serviceTable.Update(
  164. updateItems.Select(t => t.Item1).ToList(),
  165. updateItems.Select(t => t.Item2).ToList());
  166. return true;
  167. }
  168. catch (Exception ex)
  169. {
  170. log.Error(ex);
  171. }
  172. return false;
  173. }
  174. /// <summary>
  175. /// 获取远程桌面的开启状态
  176. /// </summary>
  177. /// <returns></returns>
  178. private bool? GetTSState()
  179. {
  180. try
  181. {
  182. #if WINDOWS || NETFRAMEWORK
  183. Microsoft.Win32.RegistryKey registryRoot = Microsoft.Win32.Registry.LocalMachine;
  184. string[] path = new string[] { "SYSTEM", "CurrentControlSet", "Control", "Terminal Server", "" };
  185. foreach (string p in path)
  186. {
  187. if (registryRoot != null)
  188. registryRoot = registryRoot.OpenSubKey(p);
  189. }
  190. if (registryRoot != null)
  191. {
  192. return (int)registryRoot.GetValue("fDenyTSConnections") == 0;
  193. }
  194. #endif
  195. }
  196. catch (Exception)
  197. {
  198. }
  199. return null;
  200. }
  201. /// <summary>
  202. ///
  203. /// </summary>
  204. /// <returns></returns>
  205. public bool Stop()
  206. {
  207. if (isDisposed == false)
  208. {
  209. isDisposed = true;
  210. DisposeResource();
  211. }
  212. return true;
  213. }
  214. /// <summary>
  215. ///
  216. /// </summary>
  217. /// <returns></returns>
  218. public bool Paused()
  219. {
  220. //foreach (var item in MachineManage.GetInstance().GetAllMachine())
  221. //{
  222. // item.BaseProtocol?.Pause();
  223. //}
  224. //foreach (var item in Env.Instruments)
  225. //{
  226. // item.Value.Dispose();
  227. //}
  228. return true;
  229. }
  230. /// <summary>
  231. ///
  232. /// </summary>
  233. /// <returns></returns>
  234. public bool Resume()
  235. {
  236. //foreach (var item in MachineManage.GetInstance().GetAllMachine())
  237. //{
  238. // item.BaseProtocol?.Resume();
  239. //}
  240. return true;
  241. }
  242. /// <summary>
  243. ///
  244. /// </summary>
  245. /// <returns></returns>
  246. public bool Restart()
  247. {
  248. DisposeResource();
  249. System.Threading.Thread.Sleep(1 * 1000);
  250. Start();
  251. return true;
  252. }
  253. private bool DisposeResource()
  254. {
  255. isDisposed = true;
  256. var services = ServiceCollection.Values.ToList();
  257. for (int i = services.Count - 1; i >= 0; i--)
  258. {
  259. var item = services[i];
  260. try
  261. {
  262. log.Debug($"服务ID:{item.ServiceId},名称:{item.ServiceName} is Stopping");
  263. item.Stop();
  264. }
  265. catch (Exception ex)
  266. {
  267. log.Error(ex);
  268. }
  269. }
  270. ServiceCollection.Clear();
  271. return true;
  272. }
  273. #region Web接口
  274. private List<Sys_Service> QueryServiceInfo()
  275. {
  276. return serviceTable.GetData().DtToList<Sys_Service>();
  277. }
  278. private bool ServiceIsRuning()
  279. {
  280. return true;
  281. }
  282. #endregion
  283. }
  284. }