/// <summary>
        /// Runs a specific scheduler and returns the resul depending on the passed flags.
        /// </summary>
        /// <param name="schedulerName">Name of the scheduler in the database.</param>
        /// <param name="maxWaitSeconds">Maimum amount of time to wait for the task to finish.</param>
        /// <returns>Result of running the taske (depends on the flags).</returns>
        /// <remarks>
        /// If maxWaitSeconds is less than or equals 0: the return result is only the result of the call
        /// to the "Run Now" button of the Edit Scheduler UI page.
        /// If waitUntilFinishes is greater than 0: this method will wait until the running task finishes and records its
        /// status in the Schedule History table and returns the recorded status in the last added record.
        /// </remarks>
        public static bool RunScheduler(string schedulerName, int maxWaitSeconds = 0)
        {
            var disabled = false;

            EnableScheduler(schedulerName);
            SetSchedulingMode(SchedulingMode.Timer);

            try
            {
                var schedulInfo = GetSchedulerByName(schedulerName);
                if (schedulInfo == null || schedulInfo.Count == 0)
                {
                    return(false);
                }

                // HOST modules have only single instance, so don't worry about receiving multiple rows
                var results  = ModuleController.GetModulesByFriendlyName(DnnDataHelper.PortalId, "Scheduler");
                var moduleId = results.SelectMany(x => x.Where(y => y.Key == "ModuleID").Select(y => (int)y.Value)).FirstOrDefault();

                Console.WriteLine(@"Triggering Scheduler: '{0}'", schedulerName);

                ScheduleHistoryInfo lastRunInfo = null;
                if (maxWaitSeconds > 0)
                {
                    var scheduleId = (int)schedulInfo["ScheduleId"];
                    lastRunInfo = LastRunningScheduleItem(scheduleId);
                }

                var resp = TriggerScheduler(schedulInfo, moduleId);

                // only OK is a successful POST in this case; all other codes are failures
                if (resp.StatusCode != HttpStatusCode.OK)
                {
                    Console.WriteLine(
                        @"Error running scheduler {0}. Status: {1} - {2}",
                        schedulerName, resp.StatusCode, resp.StatusDescription);
                    return(false);
                }

                // DisableScheduler(schedulerName); // un-necessary
                SetSchedulingMode(SchedulingMode.Disabled);
                disabled = true;

                if (maxWaitSeconds <= 0)
                {
                    return(true);
                }

                // wait for task to finish
                var latestRunInfo = WaitForTaskToFinish(lastRunInfo, maxWaitSeconds);
                return(latestRunInfo.Succeeded);
            }
            finally
            {
                if (!disabled)
                {
                    SetSchedulingMode(SchedulingMode.Disabled);
                }
            }
        }
 // clones another info with success as false
 internal ScheduleHistoryInfo(ScheduleHistoryInfo lastRunInfo)
 {
     ScheduleId        = lastRunInfo.ScheduleId;
     ScheduleHistoryId = lastRunInfo.ScheduleHistoryId;
     EndDate           = lastRunInfo.EndDate;
     Succeeded         = false;
     LogNotes          = lastRunInfo.LogNotes;
 }
 // clones another info with success as false
 internal ScheduleHistoryInfo(ScheduleHistoryInfo lastRunInfo)
 {
     this.ScheduleId        = lastRunInfo.ScheduleId;
     this.ScheduleHistoryId = lastRunInfo.ScheduleHistoryId;
     this.EndDate           = lastRunInfo.EndDate;
     this.Succeeded         = false;
     this.LogNotes          = lastRunInfo.LogNotes;
 }
        // waits for the task to add a new record in the Scheduler History table (i.e., finish)
        private static ScheduleHistoryInfo WaitForTaskToFinish(ScheduleHistoryInfo lastRunInfo, int maxWait)
        {
            var maxTime    = DateTime.Now.AddSeconds(maxWait);
            var latestInfo = LastRunningScheduleItem(lastRunInfo.ScheduleId);

            // must wait for it to update end time; not just adding a history record
            while (DateTime.Now < maxTime &&
                   (latestInfo.ScheduleHistoryId == lastRunInfo.ScheduleHistoryId ||
                    latestInfo.EndDate <= lastRunInfo.EndDate))
            {
                Thread.Sleep(250); // give time for task to finish
                latestInfo = LastRunningScheduleItem(lastRunInfo.ScheduleId);
            }

            return(latestInfo.ScheduleHistoryId == lastRunInfo.ScheduleHistoryId
                ? new ScheduleHistoryInfo(lastRunInfo)
                : latestInfo);
        }