using LocalDB.DBModel; 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 { /// /// /// public IApp AppRuntime { get; set; } /// /// /// readonly ILog log = SCADA.CommonLib.LoggerHelper.Logger.CreateLogger(typeof(ServiceHost)); /// 已经加载的服务器集合 /// public ConcurrentDictionary ServiceCollection { get; private set; } = new ConcurrentDictionary(); /// 可选服务类型 /// public Dictionary ServiceTypes { get; private set; } = new Dictionary(); /// /// /// /// /// /// 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(IApp app) { AppRuntime = app; return Start(); } /// /// /// /// public bool Start() { try { RpcService.GetInstance().Regiseter(this); var serviceTasks = new List() { }; serviceTable = AppRuntime.RuntimeInfo.LocalAppDB?.GetValueByPath("Sys_Service", true) as ITable; var services = DataTableHelper.DtToList(serviceTable.GetData())?.OrderBy(t => t.StartSquence_Int); ServiceTypes = GetPluginTypes().ToDictionary(t => t.FullName, t => t); 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.AppRuntime = AppRuntime; 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 = "启动失败"; } item.ServiceState_Str = serviceState; item.StartTime_Dt = startTime; item.ServiceMessage_Str = exMsg; } } Task.WaitAll(serviceTasks.ToArray()); (serviceTable as BaseTable).Update( services, t => new { t.ID }, t => new { t.ServiceState_Str, t.StartTime_Dt, t.ServiceMessage_Str }); 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; } /// /// /// /// /// public List GetPluginTypes() { return GetPluginTypes(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase .Replace("file:///", ""))); } /// /// /// /// /// public List GetPluginTypes(string basePath) { var typeList = new List(); var assemblys = new List(); if (Assembly.GetEntryAssembly() != null) { assemblys.Add(Assembly.GetEntryAssembly()); } assemblys.Add(Assembly.GetEntryAssembly()); var currentPath = string.IsNullOrEmpty(basePath) ? AppDomain.CurrentDomain.BaseDirectory : basePath; var files = new DirectoryInfo(currentPath).GetFiles(@"SCADA_DAQ.Plugin.*.dll"); var pluginFiles = Directory.CreateDirectory($"{currentPath}\\plugin") .GetFiles(@"SCADA_DAQ.Plugin.*.dll"); return ReflectionHelper.GetTypes(files.Concat(pluginFiles).ToLookup(t => t.Name).Select(t => t.FirstOrDefault().FullName)); } #region Web接口 private List QueryServiceInfo() { return serviceTable.GetData().DtToList(); } private bool ServiceIsRuning() { return true; } #endregion } }