Commit 8f0de60592d1528482b6b338acb039ba418b82d5

Authored by Schwirg László
1 parent 1fe85914

- Hangfire illesztés javítva

Vrh.Web.Reporting/Global.asax.cs
1 1 using System;
2 2 using System.Collections.Generic;
  3 +using System.Configuration;
3 4 using System.Diagnostics;
4 5 using System.IO;
5 6 using System.Linq;
... ... @@ -22,62 +23,28 @@ namespace Vrh.Web.Reporting
22 23 {
23 24 protected void Application_Start()
24 25 {
25   - var methodfullname = $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}";
26   -
27   - (new DCLogEntry(LogLevel.Information, methodfullname)).Write();
  26 + (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();
28 27 AreaRegistration.RegisterAllAreas();
29 28 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
30 29 RouteConfig.RegisterRoutes(RouteTable.Routes);
31 30 BundleConfig.RegisterBundles(BundleTable.Bundles);
32 31  
33   - //////////////////////////////////////////////////////////////////////////////////////
34   - ///Enable webApp pool autostart, preload and alwaysrun
35   - //////////////////////////////////////////////////////////////////////////////////////
36   - /// For web applications running on servers under your control, either physical or virtual, you can use the auto-start feature of IIS ≥ 7.5 shipped with
37   - /// Windows Server ≥ 2008 R2. Full setup requires the following steps to be done. Enable automatic start and AlwaysRunning mode for Application pool
38   - /// and configure Auto - start feature as written below.
39   - /// Edit the following file: C:\Windows\System32\inetsrv\config\applicationHost.config.
40   - /// All edits should be made below the <configuration><system.applicationHost> section.
41   - /// In the <applicationPools> section find the <add name="YourApplicationPoolName"> tag of the application pool to be autostarted.
42   - /// Add autoStart="true" and startMode="AlwaysRunning" attributes to this <add> tag.
43   - /// In the <sites><site name="YourWebsiteName"> section find the <application path="/YourWebApplicationName" applicationPool="YourApplicationPoolName"> tag of the web application
44   - /// running on the application pool with name "YourApplicationPoolName".
45   - /// Add serviceAutoStartEnabled="true" and serviceAutoStartProvider="AnyNameForYourAutoStartProvider" attributes to this <application> tag.
46   - /// Here YourWebsiteName is the name of the website where the web application, using the application pool belongs to.
47   - /// In the <serviceAutoStartProviders> section create the following element:
48   - /// <add name="AnyNameForYourAutoStartProvider" type="FullTypeNameOfTheAutostartProviderClass, NameOfTheAssemblyContainingTheAutostartProviderClass" />
49   - /// Here AnyNameForYourAutoStartProvider can be any name, that is suitable for the xml standard.
50   - /// Here FullTypeNameOfTheAutostartProviderClass is the full type name (with namespace and class name) of the class that matches the IProcessHostPreloadClient interface;
51   - /// this class should not be within the root class of the mvc application, but for example another class on the same level! For what is in this code the tag is the following:
52   - /// <add name="ApplicationPreload" type="Vrh.Web.Reporting.ApplicationPreload, Vrh.Web.Reporting" />
53   - /// Here NameOfTheAssemblyContainingTheAutostartProviderClass is the name of (for example the dll), but without the extension.
54   - //////////////////////////////////////////////////////////////////////////////////////
  32 + HangfireBootstrapper.Init(Vrh.iScheduler.Monitor.InitHangfire);
55 33  
56   - (new HangfireBootstrapper()).Initialize();
57   -
58 34 //Vrh.Web.Menu inicializáló beállításai
59   - Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg";
60   - // ! ha azt szeretnénk, hogy a menükezelő kezelje a hitelesítést is,
61   - // ! akkor ezt itt igaz értékre kell állítani
62   - Vrh.Web.Menu.Global.IsUseAuthentication = true;
  35 + Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg";
  36 + Vrh.Web.Menu.Global.IsUseAuthentication = true;// ! ha azt szeretnénk, hogy a menükezelő kezelje a hitelesítést is, akkor ezt itt igaz értékre kell állítani
63 37 }
64 38  
65   -
66 39 protected void Application_End(object sender, EventArgs e)
67 40 {
68   - var methodfullname = $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}";
69   - (new DCLogEntry(LogLevel.Information, methodfullname)).Write();
70   - HangfireBootstrapper.Instance.Stop();
  41 + (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();
  42 + HangfireBootstrapper.Stop();
71 43 }
72 44 /// <summary>
73   - /// Ha "Internal Server Error 500" üzenetet kapsz, akkor
74   - /// ide érdemes a hívás előtt betenni egy break point-ot.
75   - /// Majd vizsgálni a this.Context.AllErrors tulajdonságot.
76   - /// Egyből kiderül, miért van az 500-as hiba :)
  45 + /// Ha "Internal Server Error 500" üzenetet kapsz, akkor ide érdemes a hívás előtt betenni egy break point-ot.
  46 + /// Majd vizsgálni a this.Context.AllErrors tulajdonságot. Egyből kiderül, miért van az 500-as hiba :)
77 47 /// </summary>
78   - protected void Application_EndRequest()
79   - {
80   - //int i = 1;
81   - }
  48 + protected void Application_EndRequest() { var thisContextAllErrors = this.Context.AllErrors; }
82 49 }
83 50 }
... ...
Vrh.Web.Reporting/HangfireBootstrapper.cs
... ... @@ -16,38 +16,200 @@ using System.Xml.Linq;
16 16 using Hangfire;
17 17 using Microsoft.Web.Administration;
18 18 using Vrh.Logger;
  19 +using System.Configuration;
19 20  
20 21 namespace Vrh.Web.HangfireBootstrapperNS
21 22 {
22 23 public class HangfireBootstrapper : IRegisteredObject, IProcessHostPreloadClient
23 24 {
  25 + /// <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.
  28 + /// </summary>
  29 + public static void InitConfig(Action<object> externalinitializer=null)
  30 + {
  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); }
  35 + finally { le.Write(); }
  36 + }
  37 + private static void _InitConfig(Action<object> externalinitializer, DCLogEntry le)
  38 + {
  39 + if (externalinitializer != null)
  40 + {
  41 + externalinitializerList.Add(externalinitializer);
  42 + le.AddDataField("ADD external initializer", $"{externalinitializer.Method.DeclaringType.FullName}.{externalinitializer.Method.Name}()");
  43 + }
  44 + }
  45 + /// <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.
  47 + /// </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)
  54 + {
  55 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
  56 + try
  57 + {
  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;
  64 +
  65 + le.AddDataField("DisablAautoStart", DisablAautoStart);
  66 + _InitConfig(externalinitializer, le);
  67 + HangfireBootstrapper.Instance._InstanceInitialize(DisablAautoStart,le);
  68 + ExecuteExternalInitializers(le);
  69 + }
  70 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); }
  71 + finally { le.Write(); }
  72 + }
  73 +
  74 + /// <summary>
  75 + /// A Hangfire rendszeer leállítását végzi;
  76 + /// Ezt a metódust meg kell hívni a IProcessHostPreloadClient működéséhez!
  77 + /// </summary>
  78 + public static void Stop()
  79 + {
  80 + (new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write();
  81 + HangfireBootstrapper.Instance._Stop();
  82 + }
  83 +
  84 + /// <summary>
  85 + /// IProcessHostPreloadClient-et megvalósító metódus, amelyet a w3w worker process újratöltésekor hív meg az IIS
  86 + /// </summary>
  87 + /// <param name="parameters"></param>
24 88 public void Preload(string[] parameters)
25 89 {
26   - var methodfullname = $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}";
27   - (new DCLogEntry(LogLevel.Information, methodfullname)).Write();
28   - Initialize();
  90 + var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}");
  91 + try
  92 + {
  93 + _InstanceInitialize(le:le);
  94 + ExecuteExternalInitializers(le);
  95 + le.AddSuccessResult("SUCCESS");
  96 + }
  97 + catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); }
  98 + finally { le.Write(); }
29 99 }
30   - public void Initialize()
  100 +
  101 + /// <summary>
  102 + /// Kell legyen egy publikus paraméter nélküli konstruktor a webapp preload funkcióhoz!!!
  103 + /// </summary>
  104 + public HangfireBootstrapper() { }
  105 +
  106 + #region private members
  107 + private static void ExecuteExternalInitializers(DCLogEntry le)
31 108 {
32   - SetupAutoStart(typeof(HangfireBootstrapper));
33   - HangfireBootstrapper.Instance.SqlDBconnectionstring = Vrh.XmlProcessing.ConnectionStringStore.GetSQL(HANGFIRESQLDBCONNECTIONSTRINGNAME);
34   - HangfireBootstrapper.Instance.Start();
35   - Vrh.iScheduler.Monitor.InitHangfire(HangfireBootstrapper.Instance._backgroundJobServer);
  109 + int numofall = externalinitializerList.Count();
  110 + int counter = externalinitializerList.Count();
  111 + if (numofall==0)
  112 + {
  113 + le.AddDebugField("External initializer","Nothing to initialize!");
  114 + }
  115 + else
  116 + {
  117 + foreach (var ei in externalinitializerList)
  118 + {
  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); }
  122 + counter++;
  123 + }
  124 + }
36 125 }
37 126  
38   - private const string HANGFIRESQLDBCONNECTIONSTRINGNAME = "MAINDBLOG4PRO";
39   - private const string CONFIGFILEDIRECTORY = @"inetsrv\config";
40   - private const string CONFIGFILENAME = @"applicationHost.config";
41   - //public const string FILEPATH = @"C:\temp\applicationHost.config";
42   - private const string POOLNAME = "Log4ProIS_REPORTING";
43   - private const string WEBAPPNAME = "/Log4ProIS-REPORTING";
44   - private const string WEBSITENAME = "Default Web Site";
45   - private const string AUTOSTARTPROVIDERNAME = "ApplicationPreload";
46   - private const string AUTOSTARTPROVIDERTYPENAME = "Vrh.Web.Reporting.ApplicationPreload";
47   - private const string AUTOSTARTPROVIDERASSEMBLYNAME = "Vrh.Web.Reporting";
  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 + }
48 136  
49   - private static bool SetupAutoStart(Type serviceAutoStartProviderType)
  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()
  146 + {
  147 + lock (_lockObject)
  148 + {
  149 + if (_started) return;
  150 + _started = true;
  151 +
  152 + HostingEnvironment.RegisterObject(this);
  153 + GlobalConfiguration.Configuration
  154 + .UseSqlServerStorage(SqlDBconnectionstring)
  155 + // Specify other options here
  156 + ;
  157 +
  158 + _backgroundJobServer = new BackgroundJobServer();
  159 + }
  160 + }
  161 +
  162 + private void _Stop()
  163 + {
  164 + lock (_lockObject)
  165 + {
  166 + if (_backgroundJobServer != null) { _backgroundJobServer.Dispose(); }
  167 + HostingEnvironment.UnregisterObject(this);
  168 + }
  169 + }
  170 +
  171 + void IRegisteredObject.Stop(bool immediate) { _Stop(); }
  172 + #endregion private members
  173 +
  174 + #region private method - SetupAutoStart
  175 + /// <summary>
  176 + /// 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.
  178 + /// Enable webApp pool autostart, preload and alwaysrun
  179 + /// For web applications running on servers under your control, either physical or virtual, you can use the auto-start feature of IIS ≥ 7.5 shipped with
  180 + /// Windows Server ≥ 2008 R2. Full setup requires the following steps to be done. Enable automatic start and AlwaysRunning mode for Application pool
  181 + /// and configure Auto - start feature as written below.
  182 + /// Edit the following file: C:\Windows\System32\inetsrv\config\applicationHost.config.
  183 + /// All edits should be made below the <configuration><system.applicationHost> section.
  184 + /// In the <applicationPools> section find the <add name="YourApplicationPoolName"> tag of the application pool to be autostarted.
  185 + /// Add autoStart="true" and startMode="AlwaysRunning" attributes to this <add> tag.
  186 + /// In the <sites><site name="YourWebsiteName"> section find the <application path="/YourWebApplicationName" applicationPool="YourApplicationPoolName"> tag of the web application
  187 + /// running on the application pool with name "YourApplicationPoolName".
  188 + /// Add preloadEnabled="true", serviceAutoStartEnabled="true" and serviceAutoStartProvider="AnyNameForYourAutoStartProvider" attributes to this <application> tag.
  189 + /// Here YourWebsiteName is the name of the website where the web application, using the application pool belongs to.
  190 + /// In the <serviceAutoStartProviders> section create the following element:
  191 + /// <add name="AnyNameForYourAutoStartProvider" type="FullTypeNameOfTheAutostartProviderClass, NameOfTheAssemblyContainingTheAutostartProviderClass" />
  192 + /// Here AnyNameForYourAutoStartProvider can be any name, that is suitable for the xml standard.
  193 + /// Here FullTypeNameOfTheAutostartProviderClass is the full type name (with namespace and class name) of the class that matches the IProcessHostPreloadClient interface;
  194 + /// this class should not be within the root class of the mvc application, but for example another class on the same level! For what is in this code the tag is the following:
  195 + /// <add name="ApplicationPreload" type="Vrh.Web.Reporting.ApplicationPreload, Vrh.Web.Reporting" />
  196 + /// Here NameOfTheAssemblyContainingTheAutostartProviderClass is the name of (for example the dll), but without the extension.
  197 + //////////////////////////////////////////////////////////////////////////////////////
  198 + /// </summary>
  199 + /// <param name="serviceAutoStartProviderType">
  200 + /// annak a class-nak a típusa, amely megvalósítja a IProcessHostPreloadClient interfészt a Preload metódus-sal,
  201 + /// amely metódus meghívásra kerül mindenkor, amikor a hozzájuk tartozó w3w worker processz ujraindításra kerül.
  202 + /// </param>
  203 + /// <param name="websitename">a website neve; alapértelmezés:a tartalmazó website</param>
  204 + /// <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>
  206 + /// <returns></returns>
  207 + private static void SetupAutoStart(Type serviceAutoStartProviderType, string websitename = null, string webapplicationname = null, string applicationpoolname = null, bool disablemode = false, DCLogEntry le = null)
50 208 {
  209 + const string CONFIGFILEDIRECTORY = @"inetsrv\config";
  210 + const string CONFIGFILENAME = @"applicationHost.config";
  211 + //const string FILEPATH = @"C:\temp\applicationHost.config";
  212 +
51 213 const string SYSTEMAPPLICATIONHOST_ELEMENT = "system.applicationHost";
52 214 const string APPLICATIONPOOLS_ELEMENT = "applicationPools";
53 215 const string SITES_ELEMENT = "sites";
... ... @@ -63,78 +225,124 @@ namespace Vrh.Web.HangfireBootstrapperNS
63 225 const string PATH_ATTRIBUTE = "path";
64 226 const string AUTOSTART_ATTRIBUTE = "autoStart";
65 227 const string STARTMODE_ATTRIBUTE = "startMode";
  228 + const string PRELOADENABLED_ATTRIBUTE = "preloadEnabled";
66 229  
67   - string applicationpoolname = GetCurrentApplicationPoolName();
68   - string websitename = System.Web.Hosting.HostingEnvironment.SiteName;
69   - string webapplicationname = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
70   - string autostartprovidername = (websitename + "____" + applicationpoolname + "____" + webapplicationname).Replace(" ", "_").Replace("-", "_").Replace("/", "_");
71   - string serviceAutoStartProviderTypeFullName = serviceAutoStartProviderType.FullName;
72   - string serviceAutoStartProviderAssassemblyName = serviceAutoStartProviderType.Assembly.GetName().Name;
73   - var methodfullname = $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}";
74   - var le = new DCLogEntry(LogLevel.Information, methodfullname);
  230 + bool writele = le == null;
  231 + if (le == null) { le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); };
75 232 try
76 233 {
  234 + websitename = websitename ?? HostingEnvironment.SiteName; //websitename = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName();
  235 + webapplicationname = webapplicationname ?? HostingEnvironment.ApplicationVirtualPath; //webapplicationname = System.Web.HttpRuntime.AppDomainAppVirtualPath;
  236 + applicationpoolname = applicationpoolname ?? GetCurrentApplicationPoolName(websitename);
  237 + string autostartprovidername = (websitename + "____" + applicationpoolname + "____" + webapplicationname).Replace(" ", "_").Replace("-", "_").Replace("/", "_");
  238 + string serviceAutoStartProviderTypeFullName = serviceAutoStartProviderType.FullName;
  239 + string serviceAutoStartProviderAssassemblyName = serviceAutoStartProviderType.Assembly.GetName().Name;
77 240 string configfilepath = Path.Combine(NativeSystemPath, CONFIGFILEDIRECTORY, CONFIGFILENAME);
78   - le.AddDataField("configfilepath", configfilepath);
79   - le.AddDataField("applicationpoolname", applicationpoolname);
80   - le.AddDataField("websitename", websitename);
81   - le.AddDataField("webapplicationname", webapplicationname);
82   - le.AddDataField("serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName);
83   - le.AddDataField("serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName);
84   -
85   -
86 241 var filecontent = System.IO.File.ReadAllText(configfilepath);
87 242 XElement configxml = XElement.Parse(filecontent, LoadOptions.PreserveWhitespace); //XElement.Load(configfilepath);
88   -
89 243 XElement myconfigrootxml = configxml.Element(XName.Get(SYSTEMAPPLICATIONHOST_ELEMENT));
  244 +
  245 + le.AddDataField("SetupAutoStart configfilepath", configfilepath);
  246 + le.AddDataField("SetupAutoStart applicationpoolname", applicationpoolname);
  247 + le.AddDataField("SetupAutoStart websitename (System.Web.Hosting.HostingEnvironment.SiteName)", websitename);
  248 + le.AddDataField("SetupAutoStart webapplicationname (System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath)", webapplicationname);
  249 + //le.AddDataField("System.Web.HttpRuntime.AppDomainAppVirtualPath", HttpRuntime.AppDomainAppVirtualPath);
  250 + //le.AddDataField("System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName()", System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName());
  251 + le.AddDataField("SetupAutoStart serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName);
  252 + le.AddDataField("SetupAutoStart serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName);
  253 +
90 254 XElement myapplicationpooladdelement = myconfigrootxml?.Element(XName.Get(APPLICATIONPOOLS_ELEMENT))?
91 255 .Elements(XName.Get(ADD_ELEMENT))?.FirstOrDefault(e => e.Attribute(XName.Get(NAME_ATTRIBUTE)).Value == applicationpoolname);
92 256 XElement mysiteapplicationelement = myconfigrootxml?.Element(XName.Get(SITES_ELEMENT))?
93 257 .Elements(XName.Get(SITE_ELEMENT))?.FirstOrDefault(e => e.Attribute(XName.Get(NAME_ATTRIBUTE)).Value == websitename)
94 258 .Elements(XName.Get(APPLICATION_ELEMENT))?.FirstOrDefault(e => e.Attribute(XName.Get(PATH_ATTRIBUTE)).Value == webapplicationname && e.Attribute(XName.Get(APPLICATIONPOOL_ATTRIBUTE)).Value == applicationpoolname);
95   - if (myapplicationpooladdelement == null) return false;
96   - if (mysiteapplicationelement == null) return false;
  259 + if (myapplicationpooladdelement == null) return;
  260 + if (mysiteapplicationelement == null) return;
97 261  
98   - bool configchanged = false;
99   - configchanged = SetOrAddAttribute(AUTOSTART_ATTRIBUTE, myapplicationpooladdelement, "true") || configchanged;
100   - configchanged = SetOrAddAttribute(STARTMODE_ATTRIBUTE, myapplicationpooladdelement, "AlwaysRunning") || configchanged;
101   - configchanged = SetOrAddAttribute(SERVICEAUTOSTARTENABLED_ATTRIBUTE, mysiteapplicationelement, "true") || configchanged;
102   - configchanged = SetOrAddAttribute(SERVICEAUTOSTARTPROVIDER_ATTRIBUTE, mysiteapplicationelement, autostartprovidername) || configchanged;
  262 + bool configchanged=false;
  263 + if (disablemode)
  264 + {
  265 + configchanged = SetOrAddAttribute(AUTOSTART_ATTRIBUTE, myapplicationpooladdelement, bool.FalseString.ToLower()) || configchanged;
  266 + configchanged = SetOrAddAttribute(STARTMODE_ATTRIBUTE, myapplicationpooladdelement, StartMode.OnDemand.ToString()) || configchanged;
  267 + configchanged = SetOrAddAttribute(SERVICEAUTOSTARTENABLED_ATTRIBUTE, mysiteapplicationelement, bool.FalseString.ToLower()) || configchanged;
  268 + configchanged = SetOrAddAttribute(PRELOADENABLED_ATTRIBUTE, mysiteapplicationelement, bool.FalseString.ToLower()) || configchanged;
  269 + configchanged = RemoveAttribute(SERVICEAUTOSTARTPROVIDER_ATTRIBUTE, mysiteapplicationelement) || configchanged;
  270 +
  271 + XElement myautostartproviderselement = myconfigrootxml.Element(XName.Get(SERVICEAUTOSTARTPROVIDERS_ELEMENT));
  272 + configchanged = RemoveElementWithSelectorAttribute(ADD_ELEMENT, myautostartproviderselement, NAME_ATTRIBUTE, autostartprovidername,removecontainerifnochild:true) || configchanged;
  273 + }
  274 + else
  275 + {
  276 + configchanged = SetOrAddAttribute(AUTOSTART_ATTRIBUTE, myapplicationpooladdelement, bool.TrueString.ToLower()) || configchanged;
  277 + configchanged = SetOrAddAttribute(STARTMODE_ATTRIBUTE, myapplicationpooladdelement, StartMode.AlwaysRunning.ToString()) || configchanged;
  278 + configchanged = SetOrAddAttribute(SERVICEAUTOSTARTENABLED_ATTRIBUTE, mysiteapplicationelement, bool.TrueString.ToLower()) || configchanged;
  279 + configchanged = SetOrAddAttribute(PRELOADENABLED_ATTRIBUTE, mysiteapplicationelement, bool.TrueString.ToLower()) || configchanged;
  280 + configchanged = SetOrAddAttribute(SERVICEAUTOSTARTPROVIDER_ATTRIBUTE, mysiteapplicationelement, autostartprovidername) || configchanged;
103 281  
104   - XElement myautostartproviderselement = null;
105   - XElement myautostartprovideraddelement = null;
106   - configchanged = SetOrAddElement(SERVICEAUTOSTARTPROVIDERS_ELEMENT, myconfigrootxml, "", out myautostartproviderselement) || configchanged;
107   - configchanged = SetOrAddElementWithSelectorAttribute(ADD_ELEMENT, myautostartproviderselement, NAME_ATTRIBUTE, autostartprovidername, "", out myautostartprovideraddelement) || configchanged;
108   - configchanged = SetOrAddAttribute(TYPE_ATTRIBUTE, myautostartprovideraddelement, $"{serviceAutoStartProviderTypeFullName},{serviceAutoStartProviderAssassemblyName }") || configchanged;
  282 + configchanged = SetOrAddElement(SERVICEAUTOSTARTPROVIDERS_ELEMENT, myconfigrootxml, "", out XElement myautostartproviderselement) || configchanged;
  283 + configchanged = SetOrAddElementWithSelectorAttribute(ADD_ELEMENT, myautostartproviderselement, NAME_ATTRIBUTE, autostartprovidername, "", out XElement myautostartprovideraddelement) || configchanged;
  284 + configchanged = SetOrAddAttribute(TYPE_ATTRIBUTE, myautostartprovideraddelement, $"{serviceAutoStartProviderTypeFullName},{serviceAutoStartProviderAssassemblyName }") || configchanged;
  285 + }
109 286  
110 287 if (configchanged)
111 288 {
112 289 //configxml.Save(configfilepath);
113 290 System.IO.File.WriteAllText(configfilepath, configxml.ToString());
114 291 }
115   - le.AddDataField("configchanged", configchanged);
116   - //le.AddDataField("myconfigrootxml", myconfigrootxml);
117   - le.AddSuccessResult("SUCCESS");
118   - return true;
  292 + string modetxt = disablemode ? "DISABLED" : "ENABLED";
  293 + le.AddSuccessResult("SetupAutoStart " + (configchanged ? $"SUCCESSFULLY {modetxt}" : $"NO CHANGE, ALREADY {modetxt}"));
119 294 }
120   - catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); return false; }
121   - finally { le.Write(); }
  295 + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); return; }
  296 + finally { if (writele) le.Write(); }
  297 + }
  298 + private static bool RemoveAttribute(string attributetoremovename, XElement attrcontainer)
  299 + {
  300 + XAttribute attr = attrcontainer.Attribute(XName.Get(attributetoremovename));
  301 + if (attr == null) return false;
  302 + attr.Remove();
  303 + return true;
122 304 }
123   - private static bool SetOrAddElement(string elementname, XElement elementcontainer, string elementvalue, out XElement myelement)
  305 + private static bool RemoveElement(string elementtoremovename, XElement elementcontainer,bool removecontainerifnochild=false)
124 306 {
125 307 bool configchanged = false;
126   - myelement = elementcontainer?.Element(XName.Get(elementname));
127   - if (myelement == null) { myelement = new XElement(XName.Get(elementname), ""); elementcontainer.Add(myelement); configchanged = true; }
  308 + XElement elementtoremove = elementcontainer?.Element(XName.Get(elementtoremovename));
  309 + if (elementtoremove == null) return configchanged;
  310 + elementtoremove.Remove();
  311 + if (removecontainerifnochild)
  312 + {
  313 + var childelements = elementcontainer.Elements();
  314 + if (childelements == null || !childelements.Any()) elementcontainer.Remove();
  315 + }
  316 + return (configchanged=true);
  317 + }
  318 + private static bool RemoveElementWithSelectorAttribute(string elementtoremovename, XElement elementcontainer,string selectorattributename, string selectorattributevalue,bool removecontainerifnochild=false)
  319 + {
  320 + bool configchanged = false;
  321 + XElement elementtoremove = elementcontainer?.Elements(XName.Get(elementtoremovename))?.FirstOrDefault(e => e.Attribute(XName.Get(selectorattributename)).Value == selectorattributevalue);
  322 + if (elementtoremove == null) return configchanged;
  323 + elementtoremove.Remove();
  324 + if (removecontainerifnochild)
  325 + {
  326 + var childelements = elementcontainer.Elements();
  327 + if (childelements == null || !childelements.Any()) elementcontainer.Remove();
  328 + }
  329 + return (configchanged = true);
  330 + }
  331 + private static bool SetOrAddElement(string elementtosetname, XElement elementcontainer, string elementvalue, out XElement myelement)
  332 + {
  333 + bool configchanged = false;
  334 + myelement = elementcontainer?.Element(XName.Get(elementtosetname));
  335 + if (myelement == null) { myelement = new XElement(XName.Get(elementtosetname), ""); elementcontainer.Add(myelement); configchanged = true; }
128 336 if (myelement.Value != elementvalue) { myelement.Value = elementvalue; configchanged = true; }
129 337 return configchanged;
130 338 }
131   - private static bool SetOrAddElementWithSelectorAttribute(string elementname, XElement elementcontainer, string selectorattributename, string selectorattributevalue, string elementvalue, out XElement myelement)
  339 + private static bool SetOrAddElementWithSelectorAttribute(string elementtosetname, XElement elementcontainer, string selectorattributename, string selectorattributevalue, string elementvalue, out XElement myelement)
132 340 {
133 341 bool configchanged = false;
134   - myelement = elementcontainer?.Elements(XName.Get(elementname))?.FirstOrDefault(e => e.Attribute(XName.Get(selectorattributename)).Value == selectorattributevalue);
  342 + myelement = elementcontainer?.Elements(XName.Get(elementtosetname))?.FirstOrDefault(e => e.Attribute(XName.Get(selectorattributename)).Value == selectorattributevalue);
135 343 if (myelement == null)
136 344 {
137   - myelement = new XElement(XName.Get(elementname), "");
  345 + myelement = new XElement(XName.Get(elementtosetname), "");
138 346 elementcontainer.Add(myelement);
139 347 SetOrAddAttribute(selectorattributename, myelement, selectorattributevalue);
140 348 configchanged = true;
... ... @@ -142,76 +350,24 @@ namespace Vrh.Web.HangfireBootstrapperNS
142 350 if (myelement.Value != elementvalue) { myelement.Value = elementvalue; configchanged = true; }
143 351 return configchanged;
144 352 }
145   - private static bool SetOrAddAttribute(string attrname, XElement attrcontainer, string attrvalue)
  353 + private static bool SetOrAddAttribute(string attributetosetname, XElement attrcontainer, string attrvalue)
146 354 {
147 355 bool configchanged = false;
148   - XAttribute attr = attrcontainer.Attribute(XName.Get(attrname));
149   - if (attr == null) { attr = new XAttribute(XName.Get(attrname), ""); attrcontainer.Add(attr); configchanged = true; }
  356 + XAttribute attr = attrcontainer.Attribute(XName.Get(attributetosetname));
  357 + if (attr == null) { attr = new XAttribute(XName.Get(attributetosetname), ""); attrcontainer.Add(attr); configchanged = true; }
150 358 if (attr.Value != attrvalue) { attr.Value = attrvalue; configchanged = true; }
151 359 return configchanged;
152 360 }
153 361 private static string NativeSystemPath
154 362 {
155   - get
156   - {
157   - if (Environment.Is64BitOperatingSystem)
158   - {
159   - return System.IO.Path.Combine(
160   - Environment.GetFolderPath(Environment.SpecialFolder.Windows),
161   - "Sysnative");
162   - }
163   - return Environment.GetFolderPath(Environment.SpecialFolder.System);
164   - }
  363 + get { return System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), Environment.Is64BitOperatingSystem?"Sysnative":""); }
165 364 }
166   -
167   - private static string GetCurrentApplicationPoolName()
  365 + private static string GetCurrentApplicationPoolName(string websitename=null)
168 366 {
169   - string appPoolName = string.Empty;
170   - foreach (Application app in (new ServerManager()).Sites[System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName()].Applications)
171   - {
172   - if (app.Path == HttpRuntime.AppDomainAppVirtualPath) { appPoolName = app.ApplicationPoolName; }
173   - }
174   - return appPoolName;
  367 + return (new ServerManager()).Sites[websitename ?? System.Web.Hosting.HostingEnvironment.SiteName].Applications?
  368 + .FirstOrDefault(app => app.Path == HttpRuntime.AppDomainAppVirtualPath)?
  369 + .ApplicationPoolName;
175 370 }
176   -
177   - public static readonly HangfireBootstrapper Instance = new HangfireBootstrapper();
178   - private BackgroundJobServer _backgroundJobServer { get; set; }
179   - private string SqlDBconnectionstring { get; set; } = null;
180   - private readonly object _lockObject = new object();
181   - private bool _started;
182   -
183   -
184   - public HangfireBootstrapper()
185   - {
186   - }
187   -
188   - public void Start()
189   - {
190   - lock (_lockObject)
191   - {
192   - if (_started) return;
193   - _started = true;
194   -
195   - HostingEnvironment.RegisterObject(this);
196   -
197   - GlobalConfiguration.Configuration
198   - .UseSqlServerStorage(SqlDBconnectionstring)
199   - // Specify other options here
200   - ;
201   -
202   - _backgroundJobServer = new BackgroundJobServer();
203   - }
204   - }
205   -
206   - public void Stop()
207   - {
208   - lock (_lockObject)
209   - {
210   - if (_backgroundJobServer != null) { _backgroundJobServer.Dispose(); }
211   - HostingEnvironment.UnregisterObject(this);
212   - }
213   - }
214   -
215   - void IRegisteredObject.Stop(bool immediate) { Stop(); }
  371 + #endregion private method - SetupAutoStart
216 372 }
217 373 }
... ...
Vrh.iScheduler/Monitor .cs
... ... @@ -21,7 +21,7 @@ namespace Vrh.iScheduler
21 21  
22 22 public class Monitor : IDisposable
23 23 {
24   - public static void InitHangfire(BackgroundJobServer backgroundserver)
  24 + public static void InitHangfire(object parameters)
25 25 {
26 26 string ischedulerMonitorXml = "config=ALMiSchedulerMonitor";//TODO:hogy lehet ezt paraméterben átadni??????
27 27 string ischedulerXml = ""; // vagy "config=ALMiScheduler;";
... ... @@ -29,6 +29,86 @@ namespace Vrh.iScheduler
29 29 Monitor.SetiSchedulerCommonXMLProcessor(m_xmlp);
30 30 if (m_xmlp.EnableWebAppExecution && m_xmlp.CheckInterval > 0)
31 31 {
  32 +
  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 * * * *")
  63 +
  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 +
  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"
  99 +
  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 *"
  110 +
  111 +
32 112 string intervalcron = Cron.MinuteInterval((int)(m_xmlp.CheckInterval / 60));//"*/1 * * * *"
33 113 //RecurringJob.RemoveIfExists("ischedulermonitorcycle");
34 114 RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor().Examination(null), intervalcron);
... ... @@ -100,7 +180,7 @@ namespace Vrh.iScheduler
100 180 m_timer = new Timer(m_xmlp.CheckInterval * 1000); // !!! Ez itt a jó sor !!! m_timer = new Timer(20000); meg a debug !!!
101 181 m_timer.Elapsed += OnExamination;
102 182  
103   - var le = new DCLogEntry(LogLevel.Debug, nameof(Monitor) + " constructor. Preparation ready.");
  183 + var le = new DCLogEntry(LogLevel.Information, nameof(Monitor) + " constructor. Preparation ready.");
104 184 le.AddDataField("iSchedulerMonitor xml path", m_xmlp.ScheduleMonitorXmlPath);
105 185 le.AddDataField("iScheduler xml path", m_xmlp.ScheduleXmlPath);
106 186 le.AddDataField("Scheduled object type", m_xmlp.ObjectType);
... ...