using LocalDB.DBModel; using LocalDB.DBNames; using log4net; using SCADA.CommonLib; using SCADA.CommonLib.Data.DIL; using SCADA.CommonLib.Helper; using SCADA.CommonLib.Service; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace SCADA_DAQ { /// /// /// public class ServiceHost : IServiceHost { /// /// /// readonly ILog log = SCADA.CommonLib.LoggerHelper.Logger.CreatLogger(typeof(ServiceHost)); /// /// /// public ConcurrentDictionary ServiceCollection { get; private set; } = new ConcurrentDictionary(); /// /// /// /// /// /// public T GetService(string serviceName) where T : IService { if (ServiceCollection.ContainsKey(serviceName)) { return (T)ServiceCollection[serviceName]; } return default; } /// /// /// /// /// public T GetService() where T : IService { return ServiceCollection.Values.OfType().FirstOrDefault(); } bool isDisposed = false; private ServiceHost() { } private static ServiceHost _instance; /// /// /// public static ServiceHost Instance { get => _instance ?? (_instance = new ServiceHost()); private set { _instance = value; } } private ITable serviceTable { get; set; } /// /// /// /// public bool Start() { try { RpcService.GetInstance().Regiseter(this); var serviceTasks = new List() { }; serviceTable = GlobalEnv.Instance.LocalAppDB?.GetValueByPath("Sys_Service", true) as ITable; var services = DataTableHelper.DtToList(serviceTable.GetData())?.OrderBy(t => t.StartSquence_Int); var serviceTypes = PlugInServer.Instance.GetTypes(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", ""))).ToDictionary(t => t.FullName, t => t); var updateItems = new ConcurrentBag>(); if (services == null) return false; foreach (var item in services) { if (item.IsEnable_Bit) { var exMsg = ""; var serviceState = ""; var startTime = DateTime.Now; if (serviceTypes.ContainsKey(item.ServiceType_Str)) { var task = Task.Factory.StartNew(() => { System.Diagnostics.Stopwatch st = null; try { System.Threading.Thread.Sleep(item.StartDelay_Int); log.Debug($"服务ID:{item.ID} ,类型:{item.ServiceType_Str} 开始启动"); st = new System.Diagnostics.Stopwatch(); st.Start(); var type = serviceTypes[item.ServiceType_Str]; var constructorInfoArray = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); ConstructorInfo noParameterConstructorInfo = null; foreach (ConstructorInfo constructorInfo in constructorInfoArray) { ParameterInfo[] parameterInfoArray = constructorInfo.GetParameters(); if (0 == parameterInfoArray.Length) { noParameterConstructorInfo = constructorInfo; break; } } if (null == noParameterConstructorInfo) { throw new NotSupportedException($"Service {item.ServiceType_Str} 没有默认构造函数"); } var service = (IService)noParameterConstructorInfo.Invoke(null); if (service.ConfigType != null) { service.ServiceConfig = (ObservableObject)JsonHelper.JsonDeserialize(item.ServiceConfig_Str, service.ConfigType) ?? (ObservableObject)Activator.CreateInstance(service.ConfigType); } service.ServiceId = item.ID.ToString(); service.ServiceName = item.ServiceName_Str; service.Start(); startTime = DateTime.Now; serviceState = "启动成功"; ServiceCollection.TryAdd(service.ServiceName, service); st.Stop(); log.Debug($"服务ID:{item.ID},名称:{item.ServiceName_Str},类型:{item.ServiceType_Str} 启动成功,耗时:{st.Elapsed}"); } catch (Exception ex) { log.Warn($"服务ID:{item.ID},名称:{item.ServiceName_Str},类型:{item.ServiceType_Str} 启动失败:{ex.Message}"); startTime = DateTime.Now; log.Error(ex); exMsg = ex.ToString(); } finally { st?.Stop(); } }); serviceTasks.Add(task); task.Wait(); } else { exMsg = $"没有找到 {item.ServiceName_Str}:{item.ServiceType_Str}"; log.Warn(exMsg); } if (!string.IsNullOrEmpty(exMsg)) { serviceState = "启动失败"; } updateItems.Add(new Tuple( new SelectFilterItem[] { new SelectFilterItem(T_Col_Name.Sys_Service.ID, item.ID) }, new UpdateItem[] { new UpdateItem(T_Col_Name.Sys_Service.ServiceState_Str, serviceState), new UpdateItem(T_Col_Name.Sys_Service.StartTime_Dt, startTime), new UpdateItem(T_Col_Name.Sys_Service.ServiceMessage_Str, exMsg)} )); } } Task.WaitAll(serviceTasks.ToArray()); serviceTable.Update( updateItems.Select(t => t.Item1).ToList(), updateItems.Select(t => t.Item2).ToList()); return true; } catch (Exception ex) { log.Error(ex); } return false; } /// /// 获取远程桌面的开启状态 /// /// private bool? GetTSState() { try { #if WINDOWS || NETFRAMEWORK Microsoft.Win32.RegistryKey registryRoot = Microsoft.Win32.Registry.LocalMachine; string[] path = new string[] { "SYSTEM", "CurrentControlSet", "Control", "Terminal Server", "" }; foreach (string p in path) { if (registryRoot != null) registryRoot = registryRoot.OpenSubKey(p); } if (registryRoot != null) { return (int)registryRoot.GetValue("fDenyTSConnections") == 0; } #endif } catch (Exception) { } return null; } /// /// /// /// public bool Stop() { if (isDisposed == false) { isDisposed = true; DisposeResource(); } return true; } /// /// /// /// public bool Paused() { //foreach (var item in MachineManage.GetInstance().GetAllMachine()) //{ // item.BaseProtocol?.Pause(); //} //foreach (var item in Env.Instruments) //{ // item.Value.Dispose(); //} return true; } /// /// /// /// public bool Resume() { //foreach (var item in MachineManage.GetInstance().GetAllMachine()) //{ // item.BaseProtocol?.Resume(); //} return true; } /// /// /// /// public bool Restart() { DisposeResource(); System.Threading.Thread.Sleep(1 * 1000); Start(); return true; } private bool DisposeResource() { isDisposed = true; var services = ServiceCollection.Values.ToList(); for (int i = services.Count - 1; i >= 0; i--) { var item = services[i]; try { log.Debug($"服务ID:{item.ServiceId},名称:{item.ServiceName} is Stopping"); item.Stop(); } catch (Exception ex) { log.Error(ex); } } ServiceCollection.Clear(); return true; } #region Web接口 private List QueryServiceInfo() { return serviceTable.GetData().DtToList(); } private bool ServiceIsRuning() { return true; } #endregion } }