Commit 0221e022f5bf1a564df833e7bb8dcf1bc5d23c63

Authored by Schwirg László
1 parent 88b98a18

Vrh.Web.Reporting v1.1.0.0

Vrh.iScheduler v3.3.0.0
Vrh.Web.Reporting/Global.asax.cs
@@ -16,20 +16,23 @@ using Hangfire; @@ -16,20 +16,23 @@ using Hangfire;
16 using Microsoft.Web.Administration; 16 using Microsoft.Web.Administration;
17 using Vrh.iScheduler; 17 using Vrh.iScheduler;
18 using Vrh.Logger; 18 using Vrh.Logger;
19 -using Vrh.Web.HangfireBootstrapperNS; 19 +using Vrh.Web.WebServerHostedServiceStarterNS;
20 namespace Vrh.Web.Reporting 20 namespace Vrh.Web.Reporting
21 { 21 {
22 public class MvcApplication : System.Web.HttpApplication 22 public class MvcApplication : System.Web.HttpApplication
23 { 23 {
24 protected void Application_Start() 24 protected void Application_Start()
25 { 25 {
  26 + Thread.Sleep(20000);
26 (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); 27 (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();
27 AreaRegistration.RegisterAllAreas(); 28 AreaRegistration.RegisterAllAreas();
28 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 29 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
29 RouteConfig.RegisterRoutes(RouteTable.Routes); 30 RouteConfig.RegisterRoutes(RouteTable.Routes);
30 BundleConfig.RegisterBundles(BundleTable.Bundles); 31 BundleConfig.RegisterBundles(BundleTable.Bundles);
31 32
32 - HangfireBootstrapper.Init(Vrh.iScheduler.Monitor.InitHangfire); 33 + WebServerHostedServiceStarter.Init(typeof(Vrh.iScheduler.WAHostedMonitorHangfire));
  34 + //IISHostedServiceStarter.Init(Vrh.iScheduler.WAHostedMonitorHangfire.Start, Vrh.iScheduler.WAHostedMonitorHangfire.Stop);
  35 + //IISHostedServiceStarter.Init(Vrh.iScheduler.WAHostedMonitor.Start, Vrh.iScheduler.WAHostedMonitor.Stop);
33 36
34 //Vrh.Web.Menu inicializáló beállításai 37 //Vrh.Web.Menu inicializáló beállításai
35 Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg"; 38 Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg";
@@ -39,7 +42,7 @@ namespace Vrh.Web.Reporting @@ -39,7 +42,7 @@ namespace Vrh.Web.Reporting
39 protected void Application_End(object sender, EventArgs e) 42 protected void Application_End(object sender, EventArgs e)
40 { 43 {
41 (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); 44 (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();
42 - HangfireBootstrapper.Stop(); 45 + WebServerHostedServiceStarter.Stop();
43 } 46 }
44 /// <summary> 47 /// <summary>
45 /// Ha "Internal Server Error 500" üzenetet kapsz, akkor ide érdemes a hívás előtt betenni egy break point-ot. 48 /// Ha "Internal Server Error 500" üzenetet kapsz, akkor ide érdemes a hívás előtt betenni egy break point-ot.
Vrh.Web.Reporting/Properties/AssemblyInfo.cs
@@ -36,6 +36,6 @@ using System.Runtime.InteropServices; @@ -36,6 +36,6 @@ using System.Runtime.InteropServices;
36 // You can specify all the values or you can default the Build and Revision Numbers 36 // You can specify all the values or you can default the Build and Revision Numbers
37 // by using the '*' as shown below: 37 // by using the '*' as shown below:
38 // [assembly: AssemblyVersion("1.0.*")] 38 // [assembly: AssemblyVersion("1.0.*")]
39 -[assembly: AssemblyVersion("1.0.0.0")]  
40 -[assembly: AssemblyFileVersion("1.0.0.0")]  
41 -[assembly: AssemblyInformationalVersion("1.0.0")] 39 +[assembly: AssemblyVersion("1.1.0.0")]
  40 +[assembly: AssemblyFileVersion("1.1.0.0")]
  41 +[assembly: AssemblyInformationalVersion("1.1.0")]
Vrh.Web.Reporting/Vrh.Web.Reporting.csproj
@@ -344,7 +344,7 @@ @@ -344,7 +344,7 @@
344 <Compile Include="Global.asax.cs"> 344 <Compile Include="Global.asax.cs">
345 <DependentUpon>Global.asax</DependentUpon> 345 <DependentUpon>Global.asax</DependentUpon>
346 </Compile> 346 </Compile>
347 - <Compile Include="HangfireBootstrapper.cs" /> 347 + <Compile Include="WebServerHostedServiceStarter.cs" />
348 <Compile Include="Properties\AssemblyInfo.cs" /> 348 <Compile Include="Properties\AssemblyInfo.cs" />
349 </ItemGroup> 349 </ItemGroup>
350 <ItemGroup> 350 <ItemGroup>
Vrh.Web.Reporting/HangfireBootstrapper.cs renamed to Vrh.Web.Reporting/WebServerHostedServiceStarter.cs
@@ -17,68 +17,130 @@ using Hangfire; @@ -17,68 +17,130 @@ using Hangfire;
17 using Microsoft.Web.Administration; 17 using Microsoft.Web.Administration;
18 using Vrh.Logger; 18 using Vrh.Logger;
19 using System.Configuration; 19 using System.Configuration;
  20 +using System.Reflection;
20 21
21 -namespace Vrh.Web.HangfireBootstrapperNS 22 +namespace Vrh.Web.WebServerHostedServiceStarterNS
22 { 23 {
23 - public class HangfireBootstrapper : IRegisteredObject, IProcessHostPreloadClient 24 + /// <summary>
  25 + /// TODO: ezt egy olyan helyre kellene rakni, ahol mindenhova referálható (az Vrh.Interfaces.dll egyre jobb ötletnek tűnik! Kár hogy nem hallgattam Antira!)
  26 + /// </summary>
  27 + public interface IWebServerHostedServiceStarter
  28 + {
  29 + void Start();
  30 + void Stop();
  31 + }
  32 + public class WebServerHostedServiceStarter : IRegisteredObject, IProcessHostPreloadClient
24 { 33 {
25 /// <summary> 34 /// <summary>
26 - /// Egy külső iniciátort hregisztrálására szolgál, amelyben lehetőség van a  
27 - /// paraméterként megkapott BackgroundJobServer-re ütemezett feladatokat definiálni. 35 + /// Egy hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátor meghívást végzi.
28 /// </summary> 36 /// </summary>
29 - public static void InitConfig(Action<object> externalinitializer=null) 37 + /// <param name="tt">
  38 + /// az indító és leállító metódusokat tartalmazó osztály;
  39 + /// IWebServerHostedServiceStarter interfészt meg kell valósítsa, bár ezt nem ellenőrzi, csak azt,
  40 + /// hogy az ezt jelentő 'public static void Start();' és 'public static void Stop();' metódusok megvannak-e.
  41 + /// </param>
  42 + public static void Init(Type tt)
30 { 43 {
31 - if (externalinitializer == null) return;  
32 - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");  
33 - try { _InitConfig(externalinitializer, le); }  
34 - catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); } 44 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}");
  45 + try
  46 + {
  47 + //if (!tt.GetInterfaces().Contains(typeof(IWebServerHostedServiceStarter))) throw new InterfaceErrorApplicationException(tt.FullName);
  48 +
  49 + _SetupAutoStart<WebServerHostedServiceStarter>(le: le);
  50 +
  51 + var startmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Start), BindingFlags.Public | BindingFlags.Static);
  52 + var stopmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Stop), BindingFlags.Public | BindingFlags.Static);
  53 + if (startmethod == null || startmethod.ReturnType != typeof(void) || startmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName,nameof(IWebServerHostedServiceStarter .Start));
  54 + if (stopmethod == null || stopmethod.ReturnType != typeof(void) || stopmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Stop));
  55 + IISHostedServiceStarterInstance._RegisterExternalInitializer((Action)Delegate.CreateDelegate(typeof(Action), startmethod), (Action)Delegate.CreateDelegate(typeof(Action), stopmethod), le);
  56 +
  57 + IISHostedServiceStarterInstance._StartExternalInitializers(le);
  58 + }
  59 + catch (InterfaceErrorApplicationException ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  60 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
35 finally { le.Write(); } 61 finally { le.Write(); }
36 } 62 }
37 - private static void _InitConfig(Action<object> externalinitializer, DCLogEntry le) 63 +
  64 + /// <summary>
  65 + /// Egy hosted service elindítását, paraméterezését, konfigurálását és külső iniciátorok meghívást végzi.
  66 + /// </summary>
  67 + /// <param name="externalinitializerstartmethod">az indító metódus</param>
  68 + /// <param name="externalinitializerstopmethod">a leállító metódus</param>
  69 + public static void Init(List<Type> ttList)
38 { 70 {
39 - if (externalinitializer != null) 71 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}");
  72 + try
40 { 73 {
41 - externalinitializerList.Add(externalinitializer);  
42 - le.AddDataField("ADD external initializer", $"{externalinitializer.Method.DeclaringType.FullName}.{externalinitializer.Method.Name}()"); 74 + //if (!tt.GetInterfaces().Contains(typeof(IInterface))) throw new Exception ($"{tt.FullName} does not implement {nameof(IInterface)}!");
  75 +
  76 + _SetupAutoStart<WebServerHostedServiceStarter>(le: le);
  77 + foreach (var tt in ttList)
  78 + {
  79 + try
  80 + {
  81 + var startmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Start), BindingFlags.Public | BindingFlags.Static);
  82 + var stopmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Stop), BindingFlags.Public | BindingFlags.Static);
  83 + if (startmethod == null || startmethod.ReturnType != typeof(void) || startmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Start));
  84 + if (stopmethod == null || stopmethod.ReturnType != typeof(void) || stopmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Stop));
  85 + IISHostedServiceStarterInstance._RegisterExternalInitializer((Action)Delegate.CreateDelegate(typeof(Action), startmethod), (Action)Delegate.CreateDelegate(typeof(Action), stopmethod), le);
  86 + }
  87 + catch (InterfaceErrorApplicationException ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  88 + }
  89 + IISHostedServiceStarterInstance._StartExternalInitializers(le);
43 } 90 }
  91 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  92 + finally { le.Write(); }
  93 + }
  94 +
  95 + private class InterfaceErrorApplicationException : ApplicationException
  96 + {
  97 + public InterfaceErrorApplicationException(string typename, string methodname) : base($"Class '{typename}' does not implement 'public static void {methodname}()' action!") { }
  98 + public InterfaceErrorApplicationException(string typename) : base($"Class '{typename}' does not implement '{nameof(IWebServerHostedServiceStarter)}' interface!") { }
44 } 99 }
45 /// <summary> 100 /// <summary>
46 - /// A Hangfire rendszer elindítását, paraméterezését, konfigurálását és a külső iniciátorok meghívást végzi. 101 + /// Egy hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátor meghívást végzi.
47 /// </summary> 102 /// </summary>
48 - const string HANGFIRE = "HangfireBootstrapper:";  
49 - const string HANGFIREDISABLEAUTOSTART = HANGFIRE + "disableautostart";  
50 - const bool DISABLEAUTOSTARTDEFAULT = false;  
51 - const string HANGFIREDBCONNECTIONSTRING = HANGFIRE + "dbconnectionstring";  
52 - const string HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT = "HANGFIRESQLDB";  
53 - public static void Init(Action<object> externalinitializer=null) 103 + /// <param name="externalinitializerstartmethod">az indító metódus</param>
  104 + /// <param name="externalinitializerstopmethod">a leállító metódus</param>
  105 + public static void Init(Action externalinitializerstartmethod, Action externalinitializerstopmethod)
54 { 106 {
55 - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); 107 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}");
56 try 108 try
57 { 109 {
58 - bool DisablAautoStart;  
59 - string disableautostartstring = ConfigurationManager.AppSettings[HANGFIREDISABLEAUTOSTART];  
60 - if (string.IsNullOrWhiteSpace(disableautostartstring)) DisablAautoStart = DISABLEAUTOSTARTDEFAULT;  
61 - else if (disableautostartstring.ToLower() == bool.TrueString.ToLower()) DisablAautoStart = true;  
62 - else if (disableautostartstring.ToLower() != bool.FalseString.ToLower()) DisablAautoStart = false;  
63 - else DisablAautoStart = DISABLEAUTOSTARTDEFAULT; 110 + _SetupAutoStart<WebServerHostedServiceStarter>(le: le);
  111 + IISHostedServiceStarterInstance._RegisterExternalInitializer(externalinitializerstartmethod, externalinitializerstopmethod, le);
  112 + IISHostedServiceStarterInstance._StartExternalInitializers(le);
  113 + }
  114 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  115 + finally { le.Write(); }
  116 + }
64 117
65 - le.AddDataField("DisablAautoStart", DisablAautoStart);  
66 - _InitConfig(externalinitializer, le);  
67 - HangfireBootstrapper.Instance._InstanceInitialize(DisablAautoStart,le);  
68 - ExecuteExternalInitializers(le); 118 + /// <summary>
  119 + /// Több hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátorok meghívást végzi.
  120 + /// </summary>
  121 + public static void Init(List<Tuple<Action, Action>> externalinitializerList)
  122 + {
  123 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}");
  124 + try
  125 + {
  126 + _SetupAutoStart<WebServerHostedServiceStarter>(le: le);
  127 + foreach (var ei in externalinitializerList) IISHostedServiceStarterInstance._RegisterExternalInitializer(ei.Item1, ei.Item2, le);
  128 + IISHostedServiceStarterInstance._StartExternalInitializers(le);
69 } 129 }
70 catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } 130 catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
71 finally { le.Write(); } 131 finally { le.Write(); }
72 } 132 }
73 133
74 /// <summary> 134 /// <summary>
75 - /// A Hangfire rendszeer leállítását végzi; 135 + /// A hosted serviceek leállítását végzi;
76 /// Ezt a metódust meg kell hívni a IProcessHostPreloadClient működéséhez! 136 /// Ezt a metódust meg kell hívni a IProcessHostPreloadClient működéséhez!
77 /// </summary> 137 /// </summary>
78 public static void Stop() 138 public static void Stop()
79 { 139 {
80 - (new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();  
81 - HangfireBootstrapper.Instance._Stop(); 140 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
  141 + try { IISHostedServiceStarterInstance._StopExternalInitializers(le); }
  142 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  143 + finally { le.Write(); }
82 } 144 }
83 145
84 /// <summary> 146 /// <summary>
@@ -87,11 +149,11 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -87,11 +149,11 @@ namespace Vrh.Web.HangfireBootstrapperNS
87 /// <param name="parameters"></param> 149 /// <param name="parameters"></param>
88 public void Preload(string[] parameters) 150 public void Preload(string[] parameters)
89 { 151 {
90 - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); 152 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
91 try 153 try
92 { 154 {
93 - _InstanceInitialize(le:le);  
94 - ExecuteExternalInitializers(le); 155 + _SetupAutoStart<WebServerHostedServiceStarter>(disablemode: false, le: le);
  156 + _StartExternalInitializers(le);
95 le.AddSuccessResult("SUCCESS"); 157 le.AddSuccessResult("SUCCESS");
96 } 158 }
97 catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); } 159 catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); }
@@ -101,77 +163,83 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -101,77 +163,83 @@ namespace Vrh.Web.HangfireBootstrapperNS
101 /// <summary> 163 /// <summary>
102 /// Kell legyen egy publikus paraméter nélküli konstruktor a webapp preload funkcióhoz!!! 164 /// Kell legyen egy publikus paraméter nélküli konstruktor a webapp preload funkcióhoz!!!
103 /// </summary> 165 /// </summary>
104 - public HangfireBootstrapper() { } 166 + public WebServerHostedServiceStarter() { }
  167 +
105 168
106 #region private members 169 #region private members
107 - private static void ExecuteExternalInitializers(DCLogEntry le) 170 + void IRegisteredObject.Stop(bool immediate) { Stop(); }
  171 + private void _RegisterExternalInitializer(Action externalinitializerstartmethod, Action externalinitializerstopmethod, DCLogEntry le)
108 { 172 {
109 - int numofall = externalinitializerList.Count();  
110 - int counter = externalinitializerList.Count();  
111 - if (numofall==0) 173 + if (externalinitializerstartmethod != null)
112 { 174 {
113 - le.AddDebugField("External initializer","Nothing to initialize!"); 175 + externalinitializerList.Add(Tuple.Create(externalinitializerstartmethod, externalinitializerstopmethod));
  176 + le?.AddDataField("ADD external initializer START", $"{externalinitializerstartmethod.Method.DeclaringType.FullName}.{externalinitializerstartmethod.Method.Name}()");
  177 + le?.AddDataField("ADD external initializer STOP", $"{externalinitializerstopmethod.Method.DeclaringType.FullName}.{externalinitializerstopmethod.Method.Name}()");
114 } 178 }
115 - else 179 + }
  180 + private void _StartExternalInitializers(DCLogEntry le)
  181 + {
  182 + lock (ExternalInitializerStarStopLocker)
116 { 183 {
  184 + int numofall = externalinitializerList.Count();
  185 + int counter = externalinitializerList.Count();
  186 + if (numofall == 0) { le.AddDebugField(nameof(_StartExternalInitializers), NOEXTERNALINITIALIZERSAREREGISTERED); return; }
  187 +
  188 + HostingEnvironment.RegisterObject(IISHostedServiceStarterInstance);
117 foreach (var ei in externalinitializerList) 189 foreach (var ei in externalinitializerList)
118 { 190 {
119 - var externalinitializername = $"External initializer: {ei.Method.DeclaringType.FullName}.{ei.Method.Name}()";  
120 - try { ei.Invoke(HangfireBootstrapper.Instance._backgroundJobServer); le.AddDataField($"{externalinitializername} SUCCESS",$"{counter}of{numofall}"); }  
121 - catch (Exception ex) { le.AddDataField($"{externalinitializername} EXCEPTION", ex.Message); } 191 + var externalinitializername = $"External initializer: {ei.Item1.Method.DeclaringType.FullName}.{ei.Item1.Method.Name}()";
  192 + try { ei.Item1.Invoke(); le.AddDataField($"{externalinitializername} START SUCCESS", $"{counter}of{numofall}"); }
  193 + catch (Exception ex) { le.AddDataField($"{externalinitializername} START EXCEPTION", ex.Message); }
122 counter++; 194 counter++;
123 } 195 }
124 } 196 }
125 } 197 }
126 -  
127 - private void _InstanceInitialize(bool autostartsetupdisable =false,DCLogEntry le=null)  
128 - {  
129 - string HangfireSqlDBConnectionString = ConfigurationManager.AppSettings[HANGFIREDBCONNECTIONSTRING];  
130 - if (string.IsNullOrWhiteSpace(HangfireSqlDBConnectionString)) HangfireSqlDBConnectionString = HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT;  
131 - le?.AddDataField("HangfireSqlDBConnectionString", HangfireSqlDBConnectionString);  
132 - SetupAutoStart(typeof(HangfireBootstrapper),disablemode:autostartsetupdisable,le:le);  
133 - HangfireBootstrapper.Instance.SqlDBconnectionstring = Vrh.XmlProcessing.ConnectionStringStore.GetSQL(HangfireSqlDBConnectionString);  
134 - HangfireBootstrapper.Instance._Start();  
135 - }  
136 -  
137 - private static List<Action<object>> externalinitializerList = new List<Action<object>>();  
138 - private static readonly HangfireBootstrapper Instance = new HangfireBootstrapper();  
139 - private BackgroundJobServer _backgroundJobServer { get; set; }  
140 - private string SqlDBconnectionstring { get; set; } = null;  
141 - private readonly object _lockObject = new object();  
142 - private bool _started;  
143 -  
144 -  
145 - private void _Start() 198 + private void _StopExternalInitializers(DCLogEntry le)
146 { 199 {
147 - lock (_lockObject) 200 + lock (ExternalInitializerStarStopLocker)
148 { 201 {
149 - if (_started) return;  
150 - _started = true; 202 + int numofall = externalinitializerList.Count();
  203 + int counter = externalinitializerList.Count();
  204 + if (numofall == 0) { le.AddDebugField(nameof(_StopExternalInitializers), NOEXTERNALINITIALIZERSAREREGISTERED); return; }
151 205
152 - HostingEnvironment.RegisterObject(this);  
153 - GlobalConfiguration.Configuration  
154 - .UseSqlServerStorage(SqlDBconnectionstring)  
155 - // Specify other options here  
156 - ;  
157 -  
158 - _backgroundJobServer = new BackgroundJobServer(); 206 + foreach (var ei in externalinitializerList)
  207 + {
  208 + var externalinitializername = $"External initializer: {ei.Item2.Method.DeclaringType.FullName}.{ei.Item2.Method.Name}()";
  209 + try { ei.Item2.Invoke(); le.AddDataField($"{externalinitializername} STOP SUCCESS", $"{counter}of{numofall}"); }
  210 + catch (Exception ex) { le.AddDataField($"{externalinitializername} STOP EXCEPTION", ex.Message); }
  211 + counter++;
  212 + }
  213 + HostingEnvironment.UnregisterObject(IISHostedServiceStarterInstance);
159 } 214 }
160 } 215 }
161 216
162 - private void _Stop() 217 + private object ExternalInitializerStarStopLocker = new object();
  218 + private static readonly WebServerHostedServiceStarter IISHostedServiceStarterInstance = new WebServerHostedServiceStarter();
  219 + private static List<Tuple<Action, Action>> externalinitializerList = new List<Tuple<Action, Action>>();
  220 + private static bool Config_DisablAutoStart
163 { 221 {
164 - lock (_lockObject) 222 + get
165 { 223 {
166 - if (_backgroundJobServer != null) { _backgroundJobServer.Dispose(); }  
167 - HostingEnvironment.UnregisterObject(this); 224 + if (!config_disablautostart.HasValue)
  225 + {
  226 + string disableautostartstring = ConfigurationManager.AppSettings[DISABLEAUTOSTART];
  227 + if (string.IsNullOrWhiteSpace(disableautostartstring)) config_disablautostart = DISABLEAUTOSTARTDEFAULT;
  228 + else if (disableautostartstring.ToLower() == bool.TrueString.ToLower()) config_disablautostart = true;
  229 + else if (disableautostartstring.ToLower() != bool.FalseString.ToLower()) config_disablautostart = false;
  230 + else config_disablautostart = DISABLEAUTOSTARTDEFAULT;
  231 + }
  232 + return config_disablautostart.Value;
168 } 233 }
169 } 234 }
170 -  
171 - void IRegisteredObject.Stop(bool immediate) { _Stop(); } 235 + private static bool? config_disablautostart = null;
  236 + private const string IISHOSTEDSERVICESTARTER = "IISHostedServiceStarter:";
  237 + private const string DISABLEAUTOSTART = IISHOSTEDSERVICESTARTER + "disableautostart";
  238 + private const bool DISABLEAUTOSTARTDEFAULT = false;
  239 + private const string NOEXTERNALINITIALIZERSAREREGISTERED = "No external initializers are registered!";
172 #endregion private members 240 #endregion private members
173 241
174 - #region private method - SetupAutoStart 242 + #region private method - _SetupAutoStart
175 /// <summary> 243 /// <summary>
176 /// Beállítja az autostart és alwaysrunning és a preload paramétereket a megadott websitra, 244 /// Beállítja az autostart és alwaysrunning és a preload paramétereket a megadott websitra,
177 /// web alkalmazásra és application pool-ra vonatkozóan. 245 /// web alkalmazásra és application pool-ra vonatkozóan.
@@ -204,14 +272,16 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -204,14 +272,16 @@ namespace Vrh.Web.HangfireBootstrapperNS
204 /// <param name="webapplicationname">a web app neve; alapértelmezés:a tartalmazó web app</param> 272 /// <param name="webapplicationname">a web app neve; alapértelmezés:a tartalmazó web app</param>
205 /// <param name="applicationpoolname">az app pool neve; alapértelmezés:a tartalmazó pool</param> 273 /// <param name="applicationpoolname">az app pool neve; alapértelmezés:a tartalmazó pool</param>
206 /// <returns></returns> 274 /// <returns></returns>
207 - private static void SetupAutoStart(Type serviceAutoStartProviderType, string websitename = null, string webapplicationname = null, string applicationpoolname = null, bool disablemode = false, DCLogEntry le = null) 275 + private static void _SetupAutoStart<T>(string websitename = null, string webapplicationname = null, string applicationpoolname = null, bool? disablemode = null, DCLogEntry le = null)
  276 + where T: IProcessHostPreloadClient
208 { 277 {
  278 + Type serviceAutoStartProviderType = typeof(T);
209 const string CONFIGFILEDIRECTORY = @"inetsrv\config"; 279 const string CONFIGFILEDIRECTORY = @"inetsrv\config";
210 const string CONFIGFILENAME = @"applicationHost.config"; 280 const string CONFIGFILENAME = @"applicationHost.config";
211 //const string FILEPATH = @"C:\temp\applicationHost.config"; 281 //const string FILEPATH = @"C:\temp\applicationHost.config";
212 - 282 + Thread.Sleep(20000);
213 bool writele = le == null; 283 bool writele = le == null;
214 - if (le == null) { le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); }; 284 + if (le == null) { le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); };
215 try 285 try
216 { 286 {
217 websitename = websitename ?? HostingEnvironment.SiteName; //websitename = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName(); 287 websitename = websitename ?? HostingEnvironment.SiteName; //websitename = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName();
@@ -231,6 +301,9 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -231,6 +301,9 @@ namespace Vrh.Web.HangfireBootstrapperNS
231 le.AddDataField("SetupAutoStart serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName); 301 le.AddDataField("SetupAutoStart serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName);
232 le.AddDataField("SetupAutoStart serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName); 302 le.AddDataField("SetupAutoStart serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName);
233 303
  304 + if (!disablemode.HasValue) disablemode = Config_DisablAutoStart;
  305 + le.AddDataField("DisablAautoStart", disablemode.Value);
  306 +
234 string filecontent; 307 string filecontent;
235 bool configchanged; 308 bool configchanged;
236 lock (lockerFile) 309 lock (lockerFile)
@@ -253,7 +326,7 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -253,7 +326,7 @@ namespace Vrh.Web.HangfireBootstrapperNS
253 } 326 }
254 327
255 reader = new StreamReader(file, Encoding.ASCII); 328 reader = new StreamReader(file, Encoding.ASCII);
256 - filecontent = ProcessFileContent(le, reader.ReadToEnd(), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode); 329 + filecontent = ProcessFileContent(le, reader.ReadToEnd(), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode.Value);
257 configchanged = filecontent != null; 330 configchanged = filecontent != null;
258 if (configchanged) 331 if (configchanged)
259 { 332 {
@@ -265,12 +338,12 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -265,12 +338,12 @@ namespace Vrh.Web.HangfireBootstrapperNS
265 } 338 }
266 else 339 else
267 { 340 {
268 - filecontent = ProcessFileContent(le, System.IO.File.ReadAllText(configfilepath), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode); 341 + filecontent = ProcessFileContent(le, System.IO.File.ReadAllText(configfilepath), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode.Value);
269 configchanged = filecontent != null; 342 configchanged = filecontent != null;
270 if (configchanged) System.IO.File.WriteAllText(configfilepath, filecontent); 343 if (configchanged) System.IO.File.WriteAllText(configfilepath, filecontent);
271 } 344 }
272 } 345 }
273 - string modetxt = disablemode ? "DISABLED" : "ENABLED"; 346 + string modetxt = disablemode.Value ? "DISABLED" : "ENABLED";
274 le.AddDataField("SetupAutoStart SUCCESS RESULT",configchanged ? modetxt : $"NO CHANGE, ALREADY {modetxt}"); 347 le.AddDataField("SetupAutoStart SUCCESS RESULT",configchanged ? modetxt : $"NO CHANGE, ALREADY {modetxt}");
275 } 348 }
276 catch (Exception ex) { le.AddDataField("SetupAutoStart EXCEPTION",ex.Message); le.SetLogLevel(LogLevel.Error); return; } 349 catch (Exception ex) { le.AddDataField("SetupAutoStart EXCEPTION",ex.Message); le.SetLogLevel(LogLevel.Error); return; }
@@ -405,6 +478,6 @@ namespace Vrh.Web.HangfireBootstrapperNS @@ -405,6 +478,6 @@ namespace Vrh.Web.HangfireBootstrapperNS
405 .FirstOrDefault(app => app.Path == HttpRuntime.AppDomainAppVirtualPath)? 478 .FirstOrDefault(app => app.Path == HttpRuntime.AppDomainAppVirtualPath)?
406 .ApplicationPoolName; 479 .ApplicationPoolName;
407 } 480 }
408 - #endregion private method - SetupAutoStart 481 + #endregion private method - _SetupAutoStart
409 } 482 }
410 } 483 }
Vrh.iScheduler/Monitor .cs
@@ -16,107 +16,237 @@ using System.Data.SqlClient; @@ -16,107 +16,237 @@ using System.Data.SqlClient;
16 using System.Xml.Linq; 16 using System.Xml.Linq;
17 using Hangfire; 17 using Hangfire;
18 using Hangfire.Storage; 18 using Hangfire.Storage;
  19 +using System.Web.Hosting;
  20 +using System.Configuration;
  21 +
19 namespace Vrh.iScheduler 22 namespace Vrh.iScheduler
20 { 23 {
21 -  
22 - public class Monitor : IDisposable 24 + public class WAHostedMonitorHangfire
23 { 25 {
24 - public static void InitHangfire(object parameters) 26 + /// <summary>
  27 + /// A Hangfire alrendszer inicializálását+indítását, vagy a leállítását végzi
  28 + /// </summary>
  29 + /// <param name="start">true:inicalizálás/indítás; false:leállítás</param>
  30 + public static void Start()
25 { 31 {
26 - string ischedulerMonitorXml = "config=ALMiSchedulerMonitor";//TODO:hogy lehet ezt paraméterben átadni??????  
27 - string ischedulerXml = ""; // vagy "config=ALMiScheduler;";  
28 - var m_xmlp = new iSchedulerXMLProcessor(ischedulerMonitorXml, ischedulerXml);  
29 - Monitor.SetiSchedulerCommonXMLProcessor(m_xmlp);  
30 - if (m_xmlp.EnableWebAppExecution && m_xmlp.CheckInterval > 0) 32 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WAHostedMonitorHangfire).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
  33 + try
31 { 34 {
  35 + _MonitorHangfireInstance._StartHangfire(le);
  36 + string ischedulerMonitorXml = "config=ALMiSchedulerMonitor";//TODO:hogy lehet ezt paraméterben átadni??????
  37 + string ischedulerXml = ""; // vagy "config=ALMiScheduler;";
  38 + var m_xmlp = new iSchedulerXMLProcessor(ischedulerMonitorXml, ischedulerXml);
  39 + Monitor.SetiSchedulerCommonXMLProcessor(m_xmlp);
  40 + if (m_xmlp.EnableWebAppExecution && m_xmlp.CheckInterval > 0)
  41 + {
  42 + IntervalCronExpression = Cron.MinuteInterval((int)(m_xmlp.CheckInterval / 60));//"*/1 * * * *"
  43 + //RecurringJob.RemoveIfExists("ischedulermonitorcycle");
  44 + RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor().Examination(null), IntervalCronExpression);
  45 + //var HanfireJobId = BackgroundJob.Enqueue(() => new Monitor().Examination(null));
  46 + //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), intervalcron); //minutes interval
  47 + //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), $"{(int)(m_xmlp.CheckInterval / 60)} * * * *"); // cron expression
  48 + }
  49 + }
  50 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  51 + finally { le.Write(); }
  52 + }
32 53
33 - //Cron Expression  
34 - // <minute> <hour> <day-of-month> <month> <day-of-week>  
35 - // <minute>:0-59  
36 - // <hour>:0-23  
37 - // <day-of-month>:1-31  
38 - // <month>:1-12  
39 - // <day-of-week>:0-6 (Sunday to Saturday; 7 is Sunday on some systems)  
40 - //Special Characters in Cron Expression  
41 - // * (all) all values. event should happen for every time unit. For example, “*” in the<minute> field means “for every minute.”  
42 - // ? (any) any value. used for the <day-of-month> and <day-of-week> fields. For example “?” in the<day-of-week> field and 5 in the <day-of-month>  
43 - // field means “5th of every month” irrespective of what day is this of the week.  
44 - // – (range) value range. For example, “10-11” in the<hour> field means “10th and 11th hours.”  
45 - // , (values) multiple values. For example, “MON, WED, FRI“ in <day-of-week> field means on the days “Monday, Wednesday and Friday.”  
46 - // / (increments) specifies the incremental values.For example, a “5/15” in the<minute> field means at “5, 20, 35 and 50 minutes of an hour.”  
47 - // L (last) has different meanings when used in various fields. For example, if it's applied in the <day-of-month> field, it means last day of the month,  
48 - // i.e. “31st of January” and so on as per the calendar month. It can be used with an offset value, like “L-3”,  
49 - // which denotes the “third to last day of the calendar month.” In <day-of-week>, it specifies the “last day of a week.” It can also be used with  
50 - // another value in <day-of-week>, like “6L”, which denotes the “last Friday.”  
51 - // W (weekday) determines the weekday (Monday to Friday) nearest to a given day of the month.For example, if we specify “10W” in the<day-of-month> field,  
52 - // it means the “weekday near to 10th of that month.” So if “10th” is a Saturday, the job will be triggered on “9th,” and if “10th” is a Sunday,  
53 - // it will trigger on “11th.” If we specify “1W” in <day-of-month> and if “1st” is Saturday, the job will be triggered on “3rd,” which is Monday,  
54 - // and it will not jump back to the previous month.  
55 - // # specifies the “N-th” occurrence of a weekday of the month, for example, “third Friday of the month” can be indicated as “6#3”.  
56 - //Cron Special Strings  
57 - // run once at the startup: "@reboot"  
58 - // run once a year: "@yearly" or "@annualy" (="0 0 1 1 *")  
59 - // run once a month: "@monthly" (="0 0 1 * *")  
60 - // run once a week: "@weekly" (="0 0 * * 0")  
61 - // run once a day: "@daily" or "@midnight" (="0 0 * * *")  
62 - // run hourly: "@hourly" (="0 * * * *") 54 + public static void Stop()
  55 + {
  56 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WAHostedMonitorHangfire).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
  57 + try { _MonitorHangfireInstance._StopHangfire(le); }
  58 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  59 + finally { le.Write(); }
  60 + }
63 61
64 - //At 12:00pm (noon) every day: "0 12 * * ?"  
65 - //At Every five minutes starting at 1pm and ending at 1:55pm and then starting at 6pm and ending at 6:55pm, every day: "0/5 13,18 * * ?"  
66 - //At Every minute starting at 1pm and ending at 1:05pm, every day: "0-5 13 * * ?"  
67 - //At 1:15pm and 1:45pm every Tuesday in the month of June: "15,45 13 ? 6 Tue"  
68 - //At 9:30am every Monday, Tuesday, Wednesday, Thursday and Friday: "30 9 ? *MON - FRI"  
69 - //At 9:30am on the 15th day of every month: "30 9 15 * ?"  
70 - //At 6pm on the last day of every month: "0 18 L * ?"  
71 - //At 6pm on the third to last day of every month: "0 18 L - 3 * ?"  
72 - //At 10:30am on the last Thursday of every month: "30 10 ? *5L"  
73 - //At 10am on the third Monday of every month: "0 10 ? *2#3"  
74 - //At 12 midnight on every 5th day, starting from the 10th until the end of the month: "0 0 10 / 5 * ?"  
75 62
76 - //At every hour: "0 * * * *"  
77 - //At every hour: "@hourly"  
78 - //At once a day at midnight: "0 0 * * *"  
79 - //At every Sunday at midnight: "0 0 * * 0"  
80 - //At every hour on Mondays: "0 * * *1"  
81 - //At twice a day at 6am and 6pm: "0 6,18 * * *"  
82 - //At every 10 minutes: "*/10 * * * *"  
83 - //At every minute on July 20: "* * 20 7 *"  
84 - //At every weekday(Monday to Friday) at 10pm: "0 22 * * 1-5"  
85 - //At at midnight every Tuesday: "0 0 * * 2 *"  
86 - //At every minute during January, February, and May "* * * 1,2,5 *"  
87 - //At every 10 minutes at 5am, starting from 5:10am: "10-59/10 5 * * *"  
88 - //At quarterly on the first day of the month at 8am "0 8 1 */3 *"  
89 - //At every time you turn on the system: "@reboot"  
90 - //At the first Monday of each month, at 8am: "0 8 1-7 * 1"  
91 - //At every Sunday at 4:05 am: "5 4 * * 0"  
92 - //At at 9:15 pm on the 1st and 20th of every month: "15 9 1,20 * *"  
93 - //At at midnight every Wednesday between the 1st and 15th of every month: "0 0 1,15 * 3"  
94 - //At the first day of every month at 2:15pm: "15 14 1 * *"  
95 - //At every day from Monday to Friday every hour from 8 to 5pm: "00 08-17 * * 1-5"  
96 - //At every January 1st at 6:15am: "15 6 1 1 *"  
97 - //At at midnight on the 15th of every month: "0 0 15 * *"  
98 - //At every Monday and Friday: "* * * * 1,5" 63 + /// <summary>
  64 + /// Cron Expression
  65 + /// <minute> <hour> <day-of-month> <month> <day-of-week>
  66 + /// <minute>:0-59
  67 + /// <hour>:0-23
  68 + /// <day-of-month>:1-31
  69 + /// <month>:1-12
  70 + /// <day-of-week>:0-6 (Sunday to Saturday; 7 is Sunday on some systems)
  71 + /// Special Characters in Cron Expression
  72 + /// * (all) all values. event should happen for every time unit.For example, “*” in the<minute> field means “for every minute.”
  73 + /// ? (any) any value.used for the<day-of-month> and <day-of-week> fields.For example “?” in the<day-of-week> field and 5 in the<day-of-month>
  74 + /// field means “5th of every month” irrespective of what day is this of the week.
  75 + /// – (range) value range.For example, “10-11” in the<hour> field means “10th and 11th hours.”
  76 + /// , (values) multiple values.For example, “MON, WED, FRI“ in <day-of-week> field means on the days “Monday, Wednesday and Friday.”
  77 + /// / (increments) specifies the incremental values.For example, a “5/15” in the<minute> field means at “5, 20, 35 and 50 minutes of an hour.”
  78 + ///
  79 + /// L (last) has different meanings when used in various fields. For example, if it's applied in the <day-of-month> field, it means last day of the month,
  80 + /// i.e. “31st of January” and so on as per the calendar month. It can be used with an offset value, like “L-3”,
  81 + /// which denotes the “third to last day of the calendar month.” In<day-of-week>, it specifies the “last day of a week.” It can also be used with
  82 + /// another value in <day-of-week>, like “6L”, which denotes the “last Friday.”
  83 + ///
  84 + /// W (weekday) determines the weekday (Monday to Friday) nearest to a given day of the month.For example, if we specify “10W” in the<day-of-month> field,
  85 + /// it means the “weekday near to 10th of that month.” So if “10th” is a Saturday, the job will be triggered on “9th,” and if “10th” is a Sunday,
  86 + /// it will trigger on “11th.” If we specify “1W” in <day-of-month> and if “1st” is Saturday, the job will be triggered on “3rd,” which is Monday,
  87 + /// and it will not jump back to the previous month.
  88 + /// # specifies the “N-th” occurrence of a weekday of the month, for example, “third Friday of the month” can be indicated as “6#3”.
  89 + /// Cron Special Strings
  90 + /// run once at the startup: "@reboot"
  91 + /// run once a year: "@yearly" or "@annualy" (= "0 0 1 1 *")
  92 + /// run once a month: "@monthly" (="0 0 1 * *")
  93 + /// run once a week: "@weekly" (="0 0 * * 0")
  94 + /// run once a day: "@daily" or "@midnight" (="0 0 * * *")
  95 + /// run hourly: "@hourly" (="0 * * * *")
  96 + ///
  97 + /// Cron samples
  98 + /// At 12:00pm(noon) every day: "0 12 * * ?"
  99 + /// At Every five minutes starting at 1pm and ending at 1:55pm and then starting at 6pm and ending at 6:55pm, every day: "0/5 13,18 * * ?"
  100 + /// At Every minute starting at 1pm and ending at 1:05pm, every day: "0-5 13 * * ?"
  101 + /// At 1:15pm and 1:45pm every Tuesday in the month of June: "15,45 13 ? 6 Tue"
  102 + /// At 9:30am every Monday, Tuesday, Wednesday, Thursday and Friday: "30 9 ? *MON - FRI"
  103 + /// At 9:30am on the 15th day of every month: "30 9 15 * ?"
  104 + /// At 6pm on the last day of every month: "0 18 L * ?"
  105 + /// At 6pm on the third to last day of every month: "0 18 L - 3 * ?"
  106 + /// At 10:30am on the last Thursday of every month: "30 10 ? *5L"
  107 + /// At 10am on the third Monday of every month: "0 10 ? *2#3"
  108 + /// At 12 midnight on every 5th day, starting from the 10th until the end of the month: "0 0 10 / 5 * ?"
  109 + ///
  110 + /// At every hour: "0 * * * *"
  111 + /// At every hour: "@hourly"
  112 + /// At once a day at midnight: "0 0 * * *"
  113 + /// At every Sunday at midnight: "0 0 * * 0"
  114 + /// At every hour on Mondays: "0 * * *1"
  115 + /// At twice a day at 6am and 6pm: "0 6,18 * * *"
  116 + /// At every 10 minutes: "*/10 * * * *"
  117 + /// At every minute on July 20: "* * 20 7 *"
  118 + /// At every weekday(Monday to Friday) at 10pm: "0 22 * * 1-5"
  119 + /// At at midnight every Tuesday: "0 0 * * 2 *"
  120 + /// At every minute during January, February, and May "* * * 1,2,5 *"
  121 + /// At every 10 minutes at 5am, starting from 5:10am: "10-59/10 5 * * *"
  122 + /// At quarterly on the first day of the month at 8am "0 8 1 */3 *"
  123 + /// At every time you turn on the system: "@reboot"
  124 + /// At the first Monday of each month, at 8am: "0 8 1-7 * 1"
  125 + /// At every Sunday at 4:05 am: "5 4 * * 0"
  126 + /// At at 9:15 pm on the 1st and 20th of every month: "15 9 1,20 * *"
  127 + /// At at midnight every Wednesday between the 1st and 15th of every month: "0 0 1,15 * 3"
  128 + /// At the first day of every month at 2:15pm: "15 14 1 * *"
  129 + /// At every day from Monday to Friday every hour from 8 to 5pm: "00 08-17 * * 1-5"
  130 + /// At every January 1st at 6:15am: "15 6 1 1 *"
  131 + /// At at midnight on the 15th of every month: "0 0 15 * *"
  132 + /// At every Monday and Friday: "* * * * 1,5"
  133 + ///
  134 + /// At Every Minute of Every Day: "* * * * *" or "0-59 0-23 0-31 0-12 0-7"
  135 + /// At Every 10 Minutes of Every Day: "*/10 * * * *" or "0-59/10 * * * *" or "0,10,20,30,40,50 * * * *"
  136 + /// At Every 5 Minutes of the 6am hour starting at 6:07 (tu run at 6:07, 6:012, 6:17, 6:22, 6:27, and so on until 6:57):"07-59/5 06 * * *"
  137 + /// At Every day at midnight: "0 0 * * *" or "0 0 * * 0-7"
  138 + /// At Thrice Daily: "0 */8 * * *" or "0 0-23/8 * * *" or "0 0,8,16 * * *"
  139 + /// At Every weekday at 6am: "0 06 * * 1-5"
  140 + /// At Weekends at 6am: "0 06 * * 6,7" or "0 06 * * 6-7"
  141 + /// At Once a month on the 20th at 6am: "0 06 20 * *"
  142 + /// At Every 4 days at 6am: "0 06 */4 * *"
  143 + /// At Every 4 Months at 6am on the 10th: "0 06 10 */4 *"
  144 + /// </summary>
  145 + private static string IntervalCronExpression = null;
  146 + private static WAHostedMonitorHangfire _MonitorHangfireInstance = new WAHostedMonitorHangfire();
99 147
100 - //At Every Minute of Every Day: "* * * * *" or "0-59 0-23 0-31 0-12 0-7"  
101 - //At Every 10 Minutes of Every Day: "*/10 * * * *" or "0-59/10 * * * *" or "0,10,20,30,40,50 * * * *"  
102 - //At Every 5 Minutes of the 6am hour starting at 6:07 (tu run at 6:07, 6:012, 6:17, 6:22, 6:27, and so on until 6:57):"07-59/5 06 * * *"  
103 - //At Every day at midnight: "0 0 * * *" or "0 0 * * 0-7"  
104 - //At Thrice Daily: "0 */8 * * *" or "0 0-23/8 * * *" or "0 0,8,16 * * *"  
105 - //At Every weekday at 6am: "0 06 * * 1-5"  
106 - //At Weekends at 6am: "0 06 * * 6,7" or "0 06 * * 6-7"  
107 - //At Once a month on the 20th at 6am: "0 06 20 * *"  
108 - //At Every 4 days at 6am: "0 06 */4 * *"  
109 - //At Every 4 Months at 6am on the 10th: "0 06 10 */4 *" 148 + private BackgroundJobServer _HangfireBackgroundJobServer { get; set; }
  149 + private static readonly object _HangfireStarterLocker = new object();
  150 + private static bool _HangFireRunning = false;
  151 + const string HANGFIRE = "HangfireBootstrapper:";
  152 + const string HANGFIREDBCONNECTIONSTRING = HANGFIRE + "dbconnectionstring";
  153 + const string HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT = "HANGFIRESQLDB";
  154 + private void _StartHangfire(DCLogEntry le)
  155 + {
  156 + lock (_HangfireStarterLocker)
  157 + {
  158 + le?.AddDataField("HangfireSqlDBConnectionString", Config_HangFireConnectionString);
110 159
  160 + GlobalConfiguration.Configuration
  161 + .UseSqlServerStorage(Config_HangFireConnectionString)
  162 + // Specify other options here
  163 + ;
  164 + _HangfireBackgroundJobServer = new BackgroundJobServer();
  165 + _HangFireRunning = true;
  166 + }
  167 + }
  168 + private void _StopHangfire(DCLogEntry le)
  169 + {
  170 + lock (_HangfireStarterLocker)
  171 + {
  172 + if (!_HangFireRunning) return;
  173 + le?.AddDataField("Function", nameof(_StopHangfire));
  174 + if (_HangfireBackgroundJobServer != null) { _HangfireBackgroundJobServer.Dispose(); }
  175 + _HangFireRunning = false;
  176 + }
  177 + }
  178 + private string Config_HangFireConnectionString
  179 + {
  180 + get
  181 + {
  182 + if (config_hangfireconnectionstring == null)
  183 + {
  184 + string HangfireSqlDBConnectionString = ConfigurationManager.AppSettings[HANGFIREDBCONNECTIONSTRING];
  185 + if (string.IsNullOrWhiteSpace(HangfireSqlDBConnectionString)) HangfireSqlDBConnectionString = HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT;
  186 + config_hangfireconnectionstring = ConnectionStringStore.GetSQL(HangfireSqlDBConnectionString);
  187 + }
  188 + return config_hangfireconnectionstring;
  189 + }
  190 + }
  191 + private string config_hangfireconnectionstring = null;
  192 + }
  193 +}
  194 +namespace Vrh.iScheduler
  195 +{
  196 + public class WAHostedMonitor : Monitor
  197 + {
  198 + public static void Start()
  199 + {
  200 + MonitorInstance = new Monitor(Config_scheduleMonitorXmlPath, Config_scheduleXmlPath);
  201 + MonitorInstance.Start();
  202 + new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write();
  203 + }
  204 + public static void Stop()
  205 + {
  206 + MonitorInstance.Stop();
  207 + MonitorInstance.Dispose();
  208 + new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write();
  209 + }
111 210
112 - string intervalcron = Cron.MinuteInterval((int)(m_xmlp.CheckInterval / 60));//"*/1 * * * *"  
113 - //RecurringJob.RemoveIfExists("ischedulermonitorcycle");  
114 - RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor().Examination(null), intervalcron);  
115 - //var HanfireJobId = BackgroundJob.Enqueue(() => new Monitor().Examination(null));  
116 - //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), intervalcron); //minutes interval  
117 - //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), $"{(int)(m_xmlp.CheckInterval / 60)} * * * *"); // cron expression 211 + #region private members
  212 + private static string Config_scheduleMonitorXmlPath
  213 + {
  214 + get
  215 + {
  216 + if (config_schedulemonitorxmlpath == null)
  217 + {
  218 + string schedulemonitorxmlpath = ConfigurationManager.AppSettings[ISCHEDULERMONITORXMLPATH];
  219 + config_schedulemonitorxmlpath = ConnectionStringStore.GetSQL(schedulemonitorxmlpath);
  220 + }
  221 + return config_schedulemonitorxmlpath;
  222 + }
  223 + }
  224 + private static string config_schedulemonitorxmlpath = null;
  225 + private static string Config_scheduleXmlPath
  226 + {
  227 + get
  228 + {
  229 + if (config_schedulexmlpath == null)
  230 + {
  231 + string schedulexmlpath = ConfigurationManager.AppSettings[ISCHEDULERXMLPATH];
  232 + config_schedulexmlpath = ConnectionStringStore.GetSQL(schedulexmlpath);
  233 + }
  234 + return config_schedulexmlpath;
118 } 235 }
119 } 236 }
  237 + private static string config_schedulexmlpath = null;
  238 + const string ISCHEDULER = "iScheduler:";
  239 + const string ISCHEDULERMONITORXMLPATH = ISCHEDULER + "monitorxmlpath";
  240 + const string ISCHEDULERXMLPATH = ISCHEDULER + "xmlpath";
  241 + private static Monitor MonitorInstance;
  242 + #endregion private members
  243 + }
  244 +}
  245 +
  246 +namespace Vrh.iScheduler
  247 +{
  248 + public class Monitor : IDisposable
  249 + {
120 #region Enums 250 #region Enums
121 /// <summary> 251 /// <summary>
122 /// Ütemezések lehetséges állapotai. 252 /// Ütemezések lehetséges állapotai.
@@ -140,7 +270,7 @@ namespace Vrh.iScheduler @@ -140,7 +270,7 @@ namespace Vrh.iScheduler
140 } 270 }
141 #endregion Enums 271 #endregion Enums
142 272
143 - #region Privates 273 + #region Private members
144 274
145 private Timer m_timer; 275 private Timer m_timer;
146 private iSchedulerXMLProcessor m_xmlp; 276 private iSchedulerXMLProcessor m_xmlp;
@@ -149,7 +279,7 @@ namespace Vrh.iScheduler @@ -149,7 +279,7 @@ namespace Vrh.iScheduler
149 { 279 {
150 CommonM_xmlp = m_xmlp; 280 CommonM_xmlp = m_xmlp;
151 } 281 }
152 - #endregion Privates 282 + #endregion Private members
153 283
154 #region Constructor 284 #region Constructor
155 285
@@ -198,6 +328,7 @@ namespace Vrh.iScheduler @@ -198,6 +328,7 @@ namespace Vrh.iScheduler
198 } 328 }
199 #endregion Constructor 329 #endregion Constructor
200 330
  331 + #region public methods - Start,Stop
201 public void Start() 332 public void Start()
202 { 333 {
203 new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write(); 334 new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write();
@@ -208,6 +339,7 @@ namespace Vrh.iScheduler @@ -208,6 +339,7 @@ namespace Vrh.iScheduler
208 m_timer.Stop(); 339 m_timer.Stop();
209 new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write(); 340 new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write();
210 } 341 }
  342 + #endregion public methods - Start,Stop
211 343
212 #region Private methods 344 #region Private methods
213 345
Vrh.iScheduler/Properties/AssemblyInfo.cs
@@ -32,7 +32,7 @@ using System.Runtime.InteropServices; @@ -32,7 +32,7 @@ using System.Runtime.InteropServices;
32 // You can specify all the values or you can default the Build and Revision Numbers 32 // You can specify all the values or you can default the Build and Revision Numbers
33 // by using the '*' as shown below: 33 // by using the '*' as shown below:
34 // [assembly: AssemblyVersion("1.0.*")] 34 // [assembly: AssemblyVersion("1.0.*")]
35 -[assembly: AssemblyVersion("3.2.1.0")]  
36 -[assembly: AssemblyFileVersion("3.2.1.0")]  
37 -[assembly: AssemblyInformationalVersion("3.2.1")] 35 +[assembly: AssemblyVersion("3.3.0.0")]
  36 +[assembly: AssemblyFileVersion("3.3.0.0")]
  37 +[assembly: AssemblyInformationalVersion("3.3.0")]
38 38