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
}
}