private void ServiceHelper_ServiceStopping(object sender, EventArgs eventArgs)
        {
            // Shutdown algorithm processing framework
            StopAlgorithmProcessing();

            // Dispose of run-time log
            if ((object)m_runTimeLog != null)
            {
                m_serviceHelper.ServiceComponents.Remove(m_runTimeLog);
                m_runTimeLog.ProcessException -= ProcessExceptionHandler;
                m_runTimeLog.Dispose();
                m_runTimeLog = null;
            }

            if (m_allowServiceMonitors && (object)m_serviceMonitors != null)
            {
                m_serviceMonitors.AdapterLoaded   -= ServiceMonitors_AdapterLoaded;
                m_serviceMonitors.AdapterUnloaded -= ServiceMonitors_AdapterUnloaded;
                m_serviceMonitors.Dispose();
            }

            // Deregister event handlers
            m_serviceHelper.ServiceStarting -= ServiceHelper_ServiceStarting;
            m_serviceHelper.ServiceStarted  -= ServiceHelper_ServiceStarted;
            m_serviceHelper.ServiceStopping -= ServiceHelper_ServiceStopping;

            // Detach from handler for unobserved task exceptions
            TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException;

            ShutdownHandler.InitiateSafeShutdown();
        }
        private void ServiceHelper_ServiceStarting(object sender, EventArgs <string[]> e)
        {
            ShutdownHandler.Initialize();

            // Define a run-time log
            m_runTimeLog                   = new RunTimeLog();
            m_runTimeLog.FileName          = "RunTimeLog.txt";
            m_runTimeLog.ProcessException += ProcessExceptionHandler;
            m_runTimeLog.Initialize();

            // Create a handler for unobserved task exceptions
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

            // Make sure default service settings exist
            ConfigurationFile configFile = ConfigurationFile.Current;

            string servicePath    = FilePath.GetAbsolutePath("");
            string defaultLogPath = string.Format("{0}{1}Logs{1}", servicePath, Path.DirectorySeparatorChar);

            // Initialize algorithm processing framework - this will define default system settings
            try
            {
                AlgorithmHostingEnvironment.Initialize();
            }
            catch (Exception ex)
            {
                HandleException(new InvalidOperationException($"Exception while creating framework for algorithm hosting environment: {ex.Message}", ex));
            }

            CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];

            // Makes sure exepected system settings are defined in the configuration file
            systemSettings.Add("LogPath", defaultLogPath, "Defines the path used to archive log files");
            systemSettings.Add("MaxLogFiles", DefaultMaxLogFiles, "Defines the maximum number of log files to keep");
            systemSettings.Add("AllowRemoteRestart", DefaultAllowRemoteRestart, "Controls ability to remotely restart the host service.");
            systemSettings.Add("AllowServiceMonitors", DefaultAllowServiceMonitors, "Controls ability to auto-load IServiceMonitor implementations.");
            systemSettings.Add("DefaultCulture", DefaultCulture, "Default culture to use for language, country/region and calendar formats.");
            systemSettings.Add("InputMapping", SystemSettings.InputMapping, "Mnput mapping used by algorithm for incoming data.");
            systemSettings.Add("OutputMapping", SystemSettings.OutputMapping, "Mapping used by algorithm for outgoing data.");
            systemSettings.Add("ConnectionString", SystemSettings.ConnectionString, "Connection string used by algorithm to connect to openECA data source.");
            systemSettings.Add("FramesPerSecond", SystemSettings.FramesPerSecond, "Data rate, in frames per second, expected by algorithm.");
            systemSettings.Add("LagTime", SystemSettings.LagTime, "Maximum past-time deviation tolerance, in seconds (can be sub-second), that the algorithm will tolerate.");
            systemSettings.Add("LeadTime", SystemSettings.LeadTime, "Maximum future-time deviation tolerance, in seconds (can be sub-second), that the algorithm will tolerate.");

            // Attempt to set default culture
            try
            {
                string defaultCulture = systemSettings["DefaultCulture"].ValueAs(DefaultCulture);
                CultureInfo.DefaultThreadCurrentCulture   = CultureInfo.CreateSpecificCulture(defaultCulture);   // Defaults for date formatting, etc.
                CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture(defaultCulture);   // Culture for resource strings, etc.
            }
            catch (Exception ex)
            {
                HandleException(new InvalidOperationException($"Failed to set default culture due to exception, defaulting to \"{CultureInfo.CurrentCulture.Name.ToNonNullNorEmptyString("Undetermined")}\": {ex.Message}", ex));
            }

            // Retrieve application log path as defined in the config file
            string logPath = FilePath.GetAbsolutePath(systemSettings["LogPath"].Value);

            // Make sure log directory exists
            try
            {
                if (!Directory.Exists(logPath))
                {
                    Directory.CreateDirectory(logPath);
                }
            }
            catch (Exception ex)
            {
                // Attempt to default back to common log file path
                if (!Directory.Exists(defaultLogPath))
                {
                    try
                    {
                        Directory.CreateDirectory(defaultLogPath);
                    }
                    catch
                    {
                        defaultLogPath = servicePath;
                    }
                }

                HandleException(new InvalidOperationException($"Failed to create logging directory \"{logPath}\" due to exception, defaulting to \"{defaultLogPath}\": {ex.Message}", ex));
                logPath = defaultLogPath;
            }

            int maxLogFiles = systemSettings["MaxLogFiles"].ValueAs(DefaultMaxLogFiles);

            try
            {
                Logger.FileWriter.SetPath(logPath);
                Logger.FileWriter.SetLoggingFileCount(maxLogFiles);
            }
            catch (Exception ex)
            {
                HandleException(new InvalidOperationException($"Failed to set logging path \"{logPath}\" or max file count \"{maxLogFiles}\" due to exception: {ex.Message}"));
            }

            try
            {
                Directory.SetCurrentDirectory(servicePath);
            }
            catch (Exception ex)
            {
                HandleException(new InvalidOperationException($"Failed to set current directory to execution path \"{servicePath}\" due to exception: {ex.Message}"));
            }

            // Initialize system settings as defined in configuration file
            m_allowRemoteRestart            = systemSettings["AllowRemoteRestart"].ValueAs(DefaultAllowRemoteRestart);
            m_allowServiceMonitors          = systemSettings["AllowServiceMonitors"].ValueAs(DefaultAllowServiceMonitors);
            SystemSettings.InputMapping     = systemSettings["InputMapping"].ValueAs(SystemSettings.InputMapping);
            SystemSettings.OutputMapping    = systemSettings["OutputMapping"].ValueAs(SystemSettings.OutputMapping);
            SystemSettings.ConnectionString = systemSettings["ConnectionString"].ValueAs(SystemSettings.ConnectionString);
            SystemSettings.FramesPerSecond  = systemSettings["FramesPerSecond"].ValueAs(SystemSettings.FramesPerSecond);
            SystemSettings.LagTime          = systemSettings["LagTime"].ValueAs(SystemSettings.LagTime);
            SystemSettings.LeadTime         = systemSettings["LeadTime"].ValueAs(SystemSettings.LeadTime);
        }