Пример #1
0
        /// <summary>
        /// Gets a list of alert for a specific query.
        /// </summary>
        /// <returns>Returns a list of alert which match the specific query.</returns>
        public AmiCollection <AlertMessageInfo> GetAlerts()
        {
            var parameters = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters;

            if (parameters.Count == 0)
            {
                throw new ArgumentException($"{nameof(parameters)} cannot be empty");
            }

            var expression = QueryExpressionParser.BuildLinqExpression <AlertMessage>(this.CreateQuery(parameters));

            var alertRepository = ApplicationContext.Current.GetService <IAlertRepositoryService>();

            if (alertRepository == null)
            {
                throw new InvalidOperationException($"{nameof(IAlertRepositoryService)} not found");
            }

            var alerts = new AmiCollection <AlertMessageInfo>();

            int totalCount = 0;

            alerts.CollectionItem = alertRepository.Find(expression, 0, null, out totalCount).Select(a => new AlertMessageInfo(a)).ToList();
            alerts.Size           = totalCount;

            return(alerts);
        }
Пример #2
0
        // [PolicyPermission(System.Security.Permissions.SecurityAction.Demand, PolicyId = PermissionPolicyIdentifiers.ReadMetadata)]
        internal static void ListRoles(ApplicationListParams parms)
        {
            AmiCollection list = null;
            int           tr   = 0;

            if (parms.Active)
            {
                list = m_client.Query <SecurityApplication>(o => o.ObsoletionTime.HasValue, 0, 100, out tr);
            }
            else if (parms.Locked)
            {
                list = m_client.Query <SecurityApplication>(o => o.Lockout.HasValue, 0, 100, out tr);
            }
            else
            {
                list = m_client.Query <SecurityApplication>(o => o.ObsoletionTime == null, 0, 100, out tr);
            }

            DisplayUtil.TablePrint(list.CollectionItem.OfType <SecurityApplicationInfo>(),
                                   new String[] { "SID", "Name", "Last Auth.", "Lockout", "ILA", "A" },
                                   new int[] { 38, 24, 22, 22, 4, 2 },
                                   o => o.Entity.Key,
                                   o => o.Entity.Name,
                                   o => o.Entity.LastAuthenticationXml,
                                   o => o.Entity.LockoutXml,
                                   o => o.Entity.InvalidAuthAttempts ?? 0,
                                   o => !o.Entity.ObsoletionTime.HasValue ? "*" : null);
        }
Пример #3
0
        /// <summary>
        /// Gets the code systems.
        /// </summary>
        /// <returns>Returns a list of code systems.</returns>
        /// <exception cref="System.ArgumentException">parameters</exception>
        /// <exception cref="System.InvalidOperationException">IMetadataRepositoryService</exception>
        public AmiCollection <CodeSystem> GetCodeSystems()
        {
            var parameters = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters;

            if (parameters.Count == 0)
            {
                throw new ArgumentException($"{nameof(parameters)} cannot be empty");
            }

            var expression = QueryExpressionParser.BuildLinqExpression <CodeSystem>(this.CreateQuery(parameters));

            var metadataService = ApplicationContext.Current.GetService <IMetadataRepositoryService>();

            if (metadataService == null)
            {
                throw new InvalidOperationException($"Unable to locate service: {nameof(IMetadataRepositoryService)}");
            }

            var codeSystems = new AmiCollection <CodeSystem>();

            int totalCount;

            codeSystems.CollectionItem = metadataService.FindCodeSystem(expression, 0, null, out totalCount).ToList();
            codeSystems.Size           = totalCount;

            return(codeSystems);
        }
Пример #4
0
        public override AmiCollection GetLogs()
        {
            // Get the file trace writer
            var tracerPath = Tracer.GetWriter <RolloverTextWriterTraceWriter>()?.FileName;

            if (tracerPath == null)
            {
                throw new InvalidOperationException("No file-based trace writer was found");
            }

            var logDirectory = Path.GetDirectoryName(tracerPath);
            var retVal       = new AmiCollection();

            foreach (var itm in Directory.GetFiles(logDirectory, "*.log"))
            {
                var fi = new FileInfo(itm);
                retVal.CollectionItem.Add(new LogFileInfo()
                {
                    LastWrite = fi.LastWriteTime,
                    Name      = Path.GetFileNameWithoutExtension(fi.Name),
                    Size      = fi.Length
                });
            }
            return(retVal);
        }
Пример #5
0
        /// <summary>
        /// Gets a list of certificates.
        /// </summary>
        /// <returns>Returns a list of certificates.</returns>
        public AmiCollection <X509Certificate2Info> GetCertificates()
        {
            var collection = new AmiCollection <X509Certificate2Info>();

            var certs = this.certTool.GetCertificates();

            foreach (var cert in certs)
            {
                collection.CollectionItem.Add(new X509Certificate2Info(cert.Attribute));
            }

            return(collection);
        }
Пример #6
0
        public LogFileInfo GetLog(string logId)
        {
            var logFile = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), logId + ".log");
            var retVal  = new AmiCollection <LogFileInfo>();
            var fi      = new FileInfo(logFile);

            return(new LogFileInfo()
            {
                LastWrite = fi.LastWriteTime,
                Name = fi.Name,
                Size = fi.Length,
                Contents = File.ReadAllBytes(logFile)
            });
        }
Пример #7
0
        internal static void Userlist(UserListParms parms)
        {
            var un = parms.UserName?.OfType <String>()?.FirstOrDefault();
            AmiCollection <SecurityUserInfo> users = null;

            if (parms.Locked && !String.IsNullOrEmpty(un))
            {
                users = m_client.GetUsers(o => o.UserName.Contains(un) && o.Lockout.HasValue);
            }
            else if (!String.IsNullOrEmpty(un))
            {
                users = m_client.GetUsers(o => o.UserName.Contains(un));
            }
            else
            {
                users = m_client.GetUsers(o => o.UserName != null);
            }

            if (parms.Active)
            {
                users.CollectionItem = users.CollectionItem.Where(o => !o.User.ObsoletionTime.HasValue).ToList();
            }
            if (parms.Human)
            {
                users.CollectionItem = users.CollectionItem.Where(o => o.User.UserClass == UserClassKeys.HumanUser).ToList();
            }
            else if (parms.System)
            {
                users.CollectionItem = users.CollectionItem.Where(o => o.User.UserClass != UserClassKeys.HumanUser).ToList();
            }

            Console.WriteLine("SID{0}UserName{1}Last Lgn{2}Lockout{2} ILA  A", new String(' ', 37), new String(' ', 32), new String(' ', 13));
            foreach (var usr in users.CollectionItem)
            {
                Console.WriteLine("{0}{1}{2}{3}{4}{5}{6}{5}{7}{8}{9}",
                                  usr.User.Key.Value.ToString("B"),
                                  new String(' ', 2),
                                  usr.UserName.Length > 38 ? usr.UserName.Substring(0, 38) : usr.UserName,
                                  new String(' ', usr.UserName.Length > 38 ? 2 : 40 - usr.UserName.Length),
                                  usr.User.LastLoginTime.HasValue ? usr.User.LastLoginTime?.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss") : new String(' ', 19),
                                  "  ",
                                  usr.Lockout.HasValue ? usr.User.Lockout?.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss") : new string(' ', 19),
                                  usr.User.InvalidLoginAttempts,
                                  new String(' ', 4 - usr.User.InvalidLoginAttempts.ToString().Length),
                                  usr.User.ObsoletionTime.HasValue ? "  " : " *"
                                  );
            }
        }
Пример #8
0
        public override LogFileInfo GetLog(string logId)
        {
            // Get the file trace writer
            var tracerPath = Tracer.GetWriter <RolloverTextWriterTraceWriter>()?.FileName;

            if (tracerPath == null)
            {
                throw new InvalidOperationException("No file-based trace writer was found");
            }

            var logFile = Path.Combine(Path.GetDirectoryName(tracerPath), logId + ".log");
            var retVal  = new AmiCollection();
            var fi      = new FileInfo(logFile);

            int offset = Int32.Parse(RestOperationContext.Current.IncomingRequest.QueryString["_offset"] ?? "0"),
                count  = Int32.Parse(RestOperationContext.Current.IncomingRequest.QueryString["_count"] ?? "2048");

            if (offset > fi.Length || count > fi.Length)
            {
                throw new ArgumentOutOfRangeException($"Log file {logId} is {fi.Length} but offset is greater at {offset}");
            }
            using (var fs = File.OpenRead(logFile))
            {
                // Is count specified
                byte[] buffer;
                if (offset + count > fi.Length)
                {
                    buffer = new byte[fi.Length - offset];
                }
                else
                {
                    buffer = new byte[count];
                }

                fs.Seek(offset, SeekOrigin.Begin);
                fs.Read(buffer, 0, buffer.Length);

                return(new LogFileInfo()
                {
                    Contents = buffer,
                    LastWrite = fi.LastWriteTime,
                    Name = fi.Name,
                    Size = fi.Length
                });
            }
        }
Пример #9
0
        public AmiCollection <LogFileInfo> GetLogs()
        {
            var logDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var retVal       = new AmiCollection <LogFileInfo>();

            foreach (var itm in Directory.GetFiles(logDirectory, "*.log"))
            {
                var fi = new FileInfo(itm);
                retVal.CollectionItem.Add(new LogFileInfo()
                {
                    LastWrite = fi.LastWriteTime,
                    Name      = Path.GetFileNameWithoutExtension(fi.Name),
                    Size      = fi.Length
                });
            }
            return(retVal);
        }
Пример #10
0
        internal static void Userlist(UserListParms parms)
        {
            var           un    = parms.UserName?.OfType <String>()?.FirstOrDefault();
            AmiCollection users = null;

            if (parms.Locked && !String.IsNullOrEmpty(un))
            {
                users = m_client.GetUsers(o => o.UserName.Contains(un) && o.Lockout.HasValue);
            }
            else if (!String.IsNullOrEmpty(un))
            {
                users = m_client.GetUsers(o => o.UserName.Contains(un));
            }
            else
            {
                users = m_client.GetUsers(o => o.ObsoletionTime == null);
            }

            if (parms.Active)
            {
                users.CollectionItem = users.CollectionItem.OfType <SecurityUserInfo>().Where(o => o.Entity.ObsoletionTime.HasValue).OfType <object>().ToList();
            }
            if (parms.Human)
            {
                users.CollectionItem = users.CollectionItem.OfType <SecurityUserInfo>().Where(o => o.Entity.UserClass == ActorTypeKeys.HumanUser).OfType <object>().ToList();
            }
            else if (parms.System)
            {
                users.CollectionItem = users.CollectionItem.OfType <SecurityUserInfo>().Where(o => o.Entity.UserClass != ActorTypeKeys.HumanUser).OfType <object>().ToList();
            }
            DisplayUtil.TablePrint(users.CollectionItem.OfType <SecurityUserInfo>(),
                                   new String[] { "SID", "Name", "Last Auth", "Lockout", "ILA", "A" },
                                   new int[] { 38, 24, 22, 22, 4, 2 },
                                   o => o.Entity.Key,
                                   o => o.Entity.UserName,
                                   o => o.Entity.LastLoginTimeXml,
                                   o => o.Entity.LockoutXml,
                                   o => o.Entity.InvalidLoginAttempts,
                                   o => o.Entity.ObsoletionTime.HasValue ? null : "*"
                                   );
        }
Пример #11
0
        // [PolicyPermission(System.Security.Permissions.SecurityAction.Demand, PolicyId = PermissionPolicyIdentifiers.ReadMetadata)]
        internal static void ListRoles(RoleListParams parms)
        {
            AmiCollection list = null;
            int           tr   = 0;

            if (parms.Active)
            {
                list = m_client.Query <SecurityRole>(o => o.ObsoletionTime != null, 0, 100, out tr);
            }
            else
            {
                list = m_client.Query <SecurityRole>(o => o.ObsoletionTime == null, 0, 100, out tr);
            }

            DisplayUtil.TablePrint(list.CollectionItem.OfType <SecurityRoleInfo>(),
                                   new String[] { "SID", "Name", "Description", "A" },
                                   new int[] { 38, 20, 48, 2 },
                                   o => o.Entity.Key,
                                   o => o.Entity.Name,
                                   o => o.Entity.Description,
                                   o => !o.Entity.ObsoletionTime.HasValue ? "*" : null);
        }
Пример #12
0
        /// <summary>
        /// Gets a list of submitted certificate signing requests.
        /// </summary>
        /// <returns>Returns a list of certificate signing requests.</returns>
        public AmiCollection <SubmissionInfo> GetCsrs()
        {
            AmiCollection <SubmissionInfo> collection = new AmiCollection <SubmissionInfo>();
            var certs = this.certTool.GetCertificates();

            foreach (var cert in certs)
            {
                SubmissionInfo info = new SubmissionInfo();
                foreach (var kv in cert.Attribute)
                {
                    var key = kv.Key.Replace("Request.", "");
                    var pi  = typeof(CertificateInfo).GetProperty(key, BindingFlags.Public | BindingFlags.Instance);
                    pi?.SetValue(info, kv.Value, null);
                }
                info.XmlStatusCode = (SubmissionStatus)this.certTool.GetRequestStatus(Int32.Parse(info.RequestID)).Outcome;
                if (info.XmlStatusCode == SubmissionStatus.Submission)
                {
                    collection.CollectionItem.Add(info);
                }
            }
            return(collection);
        }
Пример #13
0
        public override LogFileInfo GetLog(string logId)
        {
            var logFile = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), logId + ".log");
            var retVal  = new AmiCollection();
            var fi      = new FileInfo(logFile);

            int offset = Int32.Parse(RestOperationContext.Current.IncomingRequest.QueryString["_offset"] ?? "0"),
                count  = Int32.Parse(RestOperationContext.Current.IncomingRequest.QueryString["_count"] ?? "2048");

            if (offset > fi.Length || count > fi.Length)
            {
                throw new ArgumentOutOfRangeException($"Log file {logId} is {fi.Length} but offset is greater at {offset}");
            }
            using (var fs = File.OpenRead(logFile))
            {
                // Is count specified
                byte[] buffer;
                if (offset + count > fi.Length)
                {
                    buffer = new byte[fi.Length - offset];
                }
                else
                {
                    buffer = new byte[count];
                }

                fs.Seek(offset, SeekOrigin.Begin);
                fs.Read(buffer, 0, buffer.Length);

                return(new LogFileInfo()
                {
                    Contents = buffer,
                    LastWrite = fi.LastWriteTime,
                    Name = fi.Name,
                    Size = fi.Length
                });
            }
        }
        /// <summary>
        /// Run the mail synchronization service
        /// </summary>
        public void Run(object sender, EventArgs e, object[] parameters)
        {
            try
            {
                this.m_jobStateManager.SetState(this, JobStateType.Running);

                // We are to poll for alerts always (never push supported)
                var amiClient = new AmiServiceClient(ApplicationContext.Current.GetRestClient("ami"));
                using (this.GetCredentials(amiClient.Client, out Credentials credentials))
                {
                    amiClient.Client.Credentials = credentials;

                    // When was the last time we polled an alert?
                    var lastSync = this.m_synchronizationLogService.GetLastTime(typeof(MailMessage));
                    var syncTime = new DateTimeOffset(lastSync.GetValueOrDefault());
                    // Poll action for all alerts to "everyone"
                    AmiCollection serverAlerts = amiClient.GetMailMessages(a => a.CreationTime >= syncTime && a.RcptTo.Any(o => o.UserName == "SYSTEM")); // SYSTEM WIDE ALERTS


                    // TODO: We need to filter by users in which this tablet will be interested in
                    ParameterExpression userParameter = Expression.Parameter(typeof(SecurityUser), "u");
                    // User name filter
                    Expression userNameFilter = Expression.Equal(Expression.MakeMemberAccess(userParameter, userParameter.Type.GetRuntimeProperty("UserName")), Expression.Constant(this.m_securityConfiguration.DeviceName));

                    // Or eith other users which have logged into this tablet
                    foreach (var user in ApplicationContext.Current.GetService <IDataPersistenceService <SecurityUser> >().Query(u => u.LastLoginTime != null && u.UserName != this.m_securityConfiguration.DeviceName, AuthenticationContext.SystemPrincipal))
                    {
                        userNameFilter = Expression.OrElse(userNameFilter,
                                                           Expression.Equal(Expression.MakeMemberAccess(userParameter, userParameter.Type.GetRuntimeProperty("UserName")), Expression.Constant(user.UserName))
                                                           );
                    }

                    ParameterExpression parmExpr       = Expression.Parameter(typeof(MailMessage), "a");
                    Expression          timeExpression = Expression.GreaterThanOrEqual(
                        Expression.Convert(Expression.MakeMemberAccess(parmExpr, parmExpr.Type.GetRuntimeProperty("CreationTime")), typeof(DateTimeOffset)),
                        Expression.Constant(syncTime)
                        ),
                    // this tablet expression
                                        userExpression = Expression.Call(
                        (MethodInfo)typeof(Enumerable).GetGenericMethod("Any", new Type[] { typeof(SecurityUser) }, new Type[] { typeof(IEnumerable <SecurityUser>), typeof(Func <SecurityUser, bool>) }),
                        Expression.MakeMemberAccess(parmExpr, parmExpr.Type.GetRuntimeProperty("RcptTo")),
                        Expression.Lambda <Func <SecurityUser, bool> >(userNameFilter, userParameter));

                    serverAlerts.CollectionItem = serverAlerts.CollectionItem.Union(amiClient.GetMailMessages(Expression.Lambda <Func <MailMessage, bool> >(Expression.AndAlso(timeExpression, userExpression), parmExpr)).CollectionItem).ToList();

                    // Import the alerts
                    foreach (var itm in serverAlerts.CollectionItem.OfType <MailMessage>())
                    {
                        this.m_tracer.TraceVerbose("Importing ALERT: [{0}]: {1}", itm.TimeStamp, itm.Subject);
                        itm.Body = String.Format("<pre>{0}</pre>", itm.Body);
                        this.m_mailRepository.Broadcast(itm);
                    }

                    this.m_synchronizationLogService.Save(typeof(MailMessage), String.Empty, String.Empty, "Mail", DateTime.Now);

                    // Push alerts which I have created or updated
                    //int tc = 0;
                    //foreach(var itm in this.m_alertRepository.Find(a=> (a.TimeStamp >= lastTime ) && a.Flags != AlertMessageFlags.System, 0, null, out tc))
                    //{
                    //    if (!String.IsNullOrEmpty(itm.To))
                    //    {
                    //        this.m_tracer.TraceVerbose("Sending ALERT: [{0}]: {1}", itm.TimeStamp, itm.Subject);
                    //        if (itm.UpdatedTime != null)
                    //            amiClient.UpdateAlert(itm.Key.ToString(), new AlertMessageInfo(itm));
                    //        else
                    //            amiClient.CreateAlert(new AlertMessageInfo(itm));
                    //    }
                    //}
                    this.m_jobStateManager.SetState(this, JobStateType.Completed);
                }
            }
            catch (Exception ex)
            {
                this.m_tracer.TraceError("Could not pull alerts: {0}", ex.Message);
                this.m_jobStateManager.SetState(this, JobStateType.Aborted);
                this.m_jobStateManager.SetProgress(this, ex.Message, 0.0f);
            }
        }
Пример #15
0
        /// <summary>
        /// Start the daemon service
        /// </summary>
        public bool Start()
        {
            this.Starting?.Invoke(this, EventArgs.Empty);

            this.m_configuration         = ApplicationContext.Current.Configuration.GetSection <SynchronizationConfigurationSection>();
            this.m_securityConfiguration = ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>();

            // Application context has started
            ApplicationContext.Current.Started += (o, e) =>
            {
                try
                {
                    // We are to poll for alerts always (never push supported)
                    TimeSpan pollInterval = this.m_configuration.PollInterval == TimeSpan.MinValue ? new TimeSpan(0, 10, 0) : this.m_configuration.PollInterval;
                    this.m_alertRepository = ApplicationContext.Current.GetService <IAlertRepositoryService>();
                    Action <Object> pollAction = null;
                    pollAction = x =>
                    {
                        try
                        {
                            var amiClient = new AmiServiceClient(ApplicationContext.Current.GetRestClient("ami"));
                            amiClient.Client.Credentials = this.GetCredentials(amiClient.Client);
                            // Pull from alerts
                            if (!this.m_isRunning)
                            {
                                return;
                            }

                            // When was the last time we polled an alert?
                            var lastTime = SynchronizationLog.Current.GetLastTime(typeof(AlertMessage));

                            var syncTime = lastTime.HasValue ? new DateTimeOffset(lastTime.Value) : DateTimeOffset.Now.AddHours(-1);

                            // Poll action for all alerts to "everyone"
                            AmiCollection <AlertMessageInfo> serverAlerts = amiClient.GetAlerts(a => a.CreationTime >= lastTime && a.To.Contains("everyone"));


                            // TODO: We need to filter by users in which this tablet will be interested in

                            ParameterExpression userParameter = Expression.Parameter(typeof(SecurityUser), "u");
                            // User name filter
                            Expression userNameFilter = Expression.Equal(Expression.MakeMemberAccess(userParameter, userParameter.Type.GetRuntimeProperty("UserName")), Expression.Constant(this.m_securityConfiguration.DeviceName));

                            // Or eith other users which have logged into this tablet
                            foreach (var user in ApplicationContext.Current.GetService <IDataPersistenceService <SecurityUser> >().Query(u => u.LastLoginTime != null && u.UserName != this.m_securityConfiguration.DeviceName))
                            {
                                userNameFilter = Expression.OrElse(userNameFilter,
                                                                   Expression.Equal(Expression.MakeMemberAccess(userParameter, userParameter.Type.GetRuntimeProperty("UserName")), Expression.Constant(user.UserName))
                                                                   );
                            }

                            ParameterExpression parmExpr       = Expression.Parameter(typeof(AlertMessage), "a");
                            Expression          timeExpression = Expression.GreaterThanOrEqual(
                                Expression.Convert(Expression.MakeMemberAccess(parmExpr, parmExpr.Type.GetRuntimeProperty("CreationTime")), typeof(DateTimeOffset)),
                                Expression.Constant(syncTime)
                                ),
                            // this tablet expression
                                                userExpression = Expression.Call(
                                (MethodInfo)typeof(Enumerable).GetGenericMethod("Any", new Type[] { typeof(SecurityUser) }, new Type[] { typeof(IEnumerable <SecurityUser>), typeof(Func <SecurityUser, bool>) }),
                                Expression.MakeMemberAccess(parmExpr, parmExpr.Type.GetRuntimeProperty("RcptTo")),
                                Expression.Lambda <Func <SecurityUser, bool> >(userNameFilter, userParameter));

                            serverAlerts.CollectionItem = serverAlerts.CollectionItem.Union(amiClient.GetAlerts(Expression.Lambda <Func <AlertMessage, bool> >(Expression.AndAlso(timeExpression, userExpression), parmExpr)).CollectionItem).ToList();

                            // Import the alerts
                            foreach (var itm in serverAlerts.CollectionItem)
                            {
                                this.m_tracer.TraceVerbose("Importing ALERT: [{0}]: {1}", itm.AlertMessage.TimeStamp, itm.AlertMessage.Subject);
                                itm.AlertMessage.Body = String.Format("<pre>{0}</pre>", itm.AlertMessage.Body);
                                this.m_alertRepository.BroadcastAlert(itm.AlertMessage);
                            }

                            // Push alerts which I have created or updated
                            //int tc = 0;
                            //foreach(var itm in this.m_alertRepository.Find(a=> (a.TimeStamp >= lastTime ) && a.Flags != AlertMessageFlags.System, 0, null, out tc))
                            //{
                            //    if (!String.IsNullOrEmpty(itm.To))
                            //    {
                            //        this.m_tracer.TraceVerbose("Sending ALERT: [{0}]: {1}", itm.TimeStamp, itm.Subject);
                            //        if (itm.UpdatedTime != null)
                            //            amiClient.UpdateAlert(itm.Key.ToString(), new AlertMessageInfo(itm));
                            //        else
                            //            amiClient.CreateAlert(new AlertMessageInfo(itm));
                            //    }
                            //}

                            SynchronizationLog.Current.Save(typeof(AlertMessage), null, null, null);
                        }
                        catch (Exception ex)
                        {
                            this.m_tracer.TraceError("Could not pull alerts: {0}", ex.Message);
                        }
                        finally
                        {
                            // Re-schedule myself in the poll interval time
                            ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(pollInterval, pollAction, null);
                        }
                    };

                    //ApplicationContext.Current.GetService<IThreadPoolService>().QueueUserWorkItem(pollInterval, pollAction, null);
                    this.m_isRunning = true;

                    pollAction(null);
                }
                catch (Exception ex)
                {
                    this.m_tracer.TraceError("Error starting Alert Sync: {0}", ex.Message);
                }
                //this.m_alertRepository.Committed +=
            };

            this.Started?.Invoke(this, EventArgs.Empty);

            return(true);
        }