/// <summary>
        ///
        /// </summary>
        private void InitializeServiceComponents()
        {
            try
            {
                InitializeEventLog();
            }
            catch { }

            try
            {
                InitializePaths();

                if (!System.IO.File.Exists(this.guiExePath))
                {
                    EventLog.WriteEntry("Main application assembly file is missing.\n\n" +
                                        "Application must be properly installed in order to access required assembly information and paths.",
                                        EventLogEntryType.Error, SVC_INIT_EVENT_ID);
                    return;
                }

                if (!System.IO.File.Exists(this.thisSvcExePath))
                {
                    EventLog.WriteEntry("Service assembly file is missing.\n\n" +
                                        "Application must be properly installed in order to access required assembly information and paths.",
                                        EventLogEntryType.Error, SVC_INIT_EVENT_ID);
                    return;
                }

                try
                {
                    MattimonAgentLibrary.Tools.ProjectAssemblyAtrributes thisSvcAssemAttr =
                        new MattimonAgentLibrary.Tools.ProjectAssemblyAtrributes(
                            this.thisSvcExePath);


                    String message = "";
                    message = String.Format(

                        "{0}->InitializeServiceComponents\n\n" +
                        "Application path: {1}\n" +
                        "Service path: {2}\n" +
                        "Service path (Win32_Services->PathName): {3}\n\n" +
                        "MattimonAgentApplication.exe assembly information:\n\n" +
                        "Title: {4}\n" +
                        "Company: {5}\n" +
                        "Product: {6}\n" +
                        "Version: {7}\n\n" +
                        "CommonAppData directory: {8}",

                        ServiceName,
                        this.guiExePath,
                        this.thisSvcExePath,
                        MattimonAgentLibrary.Tools.MyServiceController.GetWin32ServicePathName(ServiceName),
                        this.thisSvcAssemAttr.AssemblyTitle,
                        this.thisSvcAssemAttr.AssemblyCompany,
                        this.thisSvcAssemAttr.AssemblyProduct,
                        this.thisSvcAssemAttr.GetAssemblyVersion(),
                        MattimonAgentLibrary.Static.Constants.CommonAppData
                        );


                    /// Initialize the local database
                    SQLiteClientDatabase = new SQLiteClientDatabase(

                        MattimonAgentLibrary.Static.Constants.CommonAppData,

                        MattimonAgentLibrary.Tools.RegistryTools.GetPublisherByDisplayName(
                            MattimonAgentLibrary.Static.MattimonRegistrySubkeyNames.DisplayName),

                        MattimonAgentLibrary.Static.MattimonRegistrySubkeyNames.DisplayName,

                        MattimonAgentLibrary.Static.Constants.LocalDatabaseName
                        );

                    long   deviceId     = SQLiteClientDatabase.GetDeviceId();
                    long   deviceTypeId = SQLiteClientDatabase.GetDeviceTypeId();
                    long   userId       = SQLiteClientDatabase.GetUserId();
                    long   companyId    = SQLiteClientDatabase.GetCompanyId();
                    double interval     = SQLiteClientDatabase.GetReportingInterval();

                    string agentId = SQLiteClientDatabase.GetAgentId();

                    // Set global variables
                    this.fetchedDeviceId     = deviceId;
                    this.fetchedDeviceTypeId = deviceTypeId;
                    this.fetchedUserId       = userId;
                    this.fetchedCompanyId    = companyId;
                    this.fetchedInterval     = interval;

                    this.fetchedAgentId = agentId;


                    // Prepare the rest request
                    this.deviceRequests =
                        new MattimonAgentLibrary.Rest.DeviceRequests();

                    // Get the device Options
                    MattimonAgentLibrary.Models.DeviceOptions deviceOptions =
                        RequestDeviceOptions(deviceId, userId, companyId);
                    /// NOTE: each time the user changes related options, the service needs to be stopped and restarted
                    /// in order for the options to take effect.
                    /// [Void if CheckOnlineOptions is called in every timer-elapsed event!]


                    this.fetchedUseAgent = deviceOptions.UseAgent;
                    this.fetchedSqlMonit = deviceOptions.MonitorSql ? 1 : 0;


                    message += String.Format(
                        "User authentication keys:\n\n" +
                        "User ID: {0}\n" +
                        "Company ID: {1}\n" +
                        "Device ID: {2}\n\n" +

                        "Device Options:\n\n" +
                        "Reporting interval (local): every {3} minute(s)\n" +
                        "Reporting inteval (server): every {4} minute(s)\n" +
                        "(Reporting interval on local and server must be identical)\n" +
                        "Email notifications: {5}",
                        userId,
                        companyId,
                        deviceId,
                        MattimonAgentLibrary.Tools.TimeSpanUtil.ConvertMillisecondsToMinutes(interval),
                        MattimonAgentLibrary.Tools.TimeSpanUtil.ConvertMillisecondsToMinutes(deviceOptions.ReportingInterval),
                        (deviceOptions.NotificationEmails ? "Enabled" : "Disabled")
                        );

                    EventLog.WriteEntry(message, EventLogEntryType.Information, SVC_INIT_EVENT_ID);

                    /// Finally, initialize the timers
                    Timer = new System.Timers.Timer
                    {
                        Interval = interval
                    };
                    Timer.Elapsed += Timer_Elapsed;
                    Timer.Start();

                    /// And the Timer that handles the update for our updater service
                    TimerUpd = new System.Timers.Timer
                    {
                        Interval = 1000 * 60 * 1
                    };
                    TimerUpd.Elapsed += TimerUpd_Elapsed;
                    TimerUpd.Start();
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry(ex.Message + "\n\n" + ex.ToString(),
                                        EventLogEntryType.Error, SVC_INIT_EVENT_ID);
                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(ex.Message + "\n\n" + ex.ToString(),
                                    EventLogEntryType.Error, SVC_INIT_EVENT_ID);
            }
        }
        /// <summary>
        /// Gets the interval options, sql monitoring option and use agent option from the server.
        /// Interval option applied to the timer only if changed.
        /// </summary>
        /// <param name="useBackgroundWorker"></param>
        private void CheckOnlineOptions(bool useBackgroundWorker = false)
        {
            if (useBackgroundWorker)
            {
                BackgroundWorker requestOptions = new BackgroundWorker();
                requestOptions.DoWork += (s, e) =>
                {
                    MattimonAgentLibrary.Models.DeviceOptions options =
                        RequestDeviceOptions(fetchedDeviceId, fetchedUserId, fetchedCompanyId);
                    e.Result = options;
                };
                requestOptions.RunWorkerCompleted += (s, e) =>
                {
                    if (e.Error != null)
                    {
                        EventLog.WriteEntry(ExceptionHelper.GetFormatedExceptionMessage(e.Error),
                                            EventLogEntryType.Error, DEVICE_OPTION_REQUEST_EVENT_ID);
                        return;
                    }

                    if (e.Result != null && e.Result is DeviceOptions options)
                    {
                        bool exception = false;
                        if (options.MySqlExceptionMessage != null)
                        {
                            EventLog.WriteEntry(options.MySqlExceptionMessage, EventLogEntryType.Error,
                                                DEVICE_OPTION_REQUEST_EVENT_ID);
                            exception = true;
                        }
                        if (options.HttpRequestException != null)
                        {
                            EventLog.WriteEntry
                                (options.HttpRequestException.Message + "\n\n" +
                                options.HttpRequestException.StackTrace +
                                (options.HttpRequestException.InnerException != null ? "\n\nInner Exception:\n\n" +
                                 options.HttpRequestException.InnerException.Message + "\n\n" +
                                 options.HttpRequestException.InnerException.StackTrace : ""),
                                EventLogEntryType.Error, DEVICE_OPTION_REQUEST_EVENT_ID);
                            exception = true;
                        }
                        if (options.Exception != null)
                        {
                            EventLog.WriteEntry
                                (options.Exception.Message + "\n\n" +
                                options.Exception.StackTrace +
                                (options.Exception.InnerException != null ? "\n\nInner Exception:\n\n" +
                                 options.Exception.InnerException.Message + "\n\n" +
                                 options.Exception.InnerException.StackTrace : ""),
                                EventLogEntryType.Error, DEVICE_OPTION_REQUEST_EVENT_ID);
                            exception = true;
                        }

                        if (options.RequestSuccess && !exception)
                        {
                            this.fetchedSqlMonit = options.MonitorSql ? 1 : 0;
                            this.fetchedUseAgent = options.UseAgent;

                            if (Timer.Interval != options.ReportingInterval)
                            {
                                this.fetchedInterval = options.ReportingInterval;
                                this.Timer.Stop();
                                this.Timer.Interval = options.ReportingInterval;;
                                this.Timer.Start();
                            }
                        }
                    }
                    requestOptions.Dispose();
                };
            }
            else
            {
                bool exception = false;

                MattimonAgentLibrary.Models.DeviceOptions options = RequestDeviceOptions(
                    fetchedDeviceId, fetchedUserId, fetchedCompanyId);

                if (options.MySqlExceptionMessage != null)
                {
                    EventLog.WriteEntry(options.MySqlExceptionMessage, EventLogEntryType.Error,
                                        DEVICE_OPTION_REQUEST_EVENT_ID);
                    exception = true;
                }
                if (options.HttpRequestException != null)
                {
                    EventLog.WriteEntry
                        (options.HttpRequestException.Message + "\n\n" +
                        options.HttpRequestException.StackTrace +
                        (options.HttpRequestException.InnerException != null ? "\n\nInner Exception:\n\n" +
                         options.HttpRequestException.InnerException.Message + "\n\n" +
                         options.HttpRequestException.InnerException.StackTrace : ""),
                        EventLogEntryType.Error, DEVICE_OPTION_REQUEST_EVENT_ID);
                    exception = true;
                }
                if (options.Exception != null)
                {
                    EventLog.WriteEntry
                        (options.Exception.Message + "\n\n" +
                        options.Exception.StackTrace +
                        (options.Exception.InnerException != null ? "\n\nInner Exception:\n\n" +
                         options.Exception.InnerException.Message + "\n\n" +
                         options.Exception.InnerException.StackTrace : ""),
                        EventLogEntryType.Error, DEVICE_OPTION_REQUEST_EVENT_ID);
                    exception = true;
                }

                if (options.RequestSuccess && !exception)
                {
                    this.fetchedSqlMonit = options.MonitorSql ? 1 : 0;
                    this.fetchedUseAgent = options.UseAgent;

                    if (Timer.Interval != options.ReportingInterval)
                    {
                        this.fetchedInterval = options.ReportingInterval;
                        this.Timer.Stop();
                        this.Timer.Interval = options.ReportingInterval;
                        this.Timer.Start();
                    }
                }
            }
        }