【问题标题】:Email me if windows service stops如果 Windows 服务停止,请给我发电子邮件
【发布时间】:2011-12-21 08:09:46
【问题描述】:

我希望能够检查某个服务是否正在运行(比如它有一个显示名称 - ServiceA)。我希望我的程序每 5 分钟检查一次服务是否仍在运行。如果没问题,它将循环并等待另外 5 分钟,然后再次检查。如果它发现 ServiceA 已停止,我希望程序给我发电子邮件并说...ServiceA 已停止运行。下面我有到目前为止我已经完成的代码,它能够将所有当前正在运行的服务和实际的显示名称拉回控制台。有人对我上面需要的代码/逻辑有任何想法吗?

namespace ServicesChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceController[] scServices;
            scServices = ServiceController.GetServices();

            Console.WriteLine("Services running on the local computer:");
            foreach (ServiceController scTemp in scServices)
            {
                if (scTemp.Status == ServiceControllerStatus.Running)
                {
                    Console.WriteLine();
                    Console.WriteLine("  Service :        {0}", scTemp.ServiceName);
                    Console.WriteLine("    Display name:    {0}", scTemp.DisplayName); 
                }
            }
            //Create a Pause....
            Console.ReadLine();
        }
    }
}

【问题讨论】:

  • 检查器停止运行时会发生什么...!
  • Windows 已经可以为您做到这一点。当服务停止或失败时,您无需编写应用程序来触发操作。
  • @Cody:Windows 能做到这一点吗?
  • @abatishchev:在“服务”管理器 (services.msc) 中,右键单击服务,然后切换到“恢复”选项卡。您可以要求 Windows 在服务的第一次、第二次和后续失败时执行各种操作,包括启动应用程序。没有理由编写轮询的应用程序。连续轮询几乎总是错误的解决方案。
  • @Cody - 如果服务失败,是否可以将其配置为发送电子邮件?

标签: c# .net windows windows-services


【解决方案1】:

将每个服务的名称放在一个数组中并检查您想要的名称是否正在运行

List<string> arr = new List<string>();    
foreach (ServiceController scTemp in scServices)
{
    if (scTemp.Status == ServiceControllerStatus.Running)
    {
        arr.add(scTemp.ServiceName);
    }
}
if (arr.Contains("YourWantedName")
{
    // loop again
}
else
{
    // send mail
}

【讨论】:

  • 对于一个 sn-p 从 c# 发送邮件:social.msdn.microsoft.com/Forums/en/netfxnetcom/thread/… 它应该包含发送简单消息所需的所有内容。
  • 请不要在 2011 年底建议使用像 ArrayList 这样的非通用容器!请改用List&lt;string&gt; 之类的泛型。
  • @abatishchev - 再次循环代码的逻辑是什么,以便我可以继续检查数组中的服务名称?
  • 你可以使用定时器,它需要每X分钟/小时调用一次这个函数。对于计时器,请在本网站或 msdn 网站上搜索
【解决方案2】:

如果您知道要查找哪一项,则无需遍历所有服务:您可以instantiate ServiceController with the service name

至于发送邮件:看看System.Net.Mail.MailMessage类。

注意:您知道您也可以只配置服务以在失败时触发操作?

【讨论】:

  • 就让服务触发一个动作而言——这是否意味着如果它停止,您可以触发它发送电子邮件?你是怎么做的?
  • 查找(或编写)一个发送电子邮件的命令行工具,并按照 Cody Gray 在他对您的问题的评论中描述的说明进行配置。
【解决方案3】:

您需要跟踪需要某种存储的服务状态。最简单的可能是跟踪服务状态的 XML 文件,可能是这样的架构

<services>
 <service name="service1" last-check="12/21/2011 13:00:05" last-status="running" />
 ...
</services>

您的监控应用会唤醒并查找它感兴趣的服务的状态,并检查该服务之前的状态是什么。如果状态为正在运行,但当前已停止,请发送电子邮件。如果未找到该服务,请将其添加到服务列表中。

将服务的状态保存到磁盘可以在您的监控应用出现故障时保护您。

【讨论】:

    【解决方案4】:

    这是一个服务的例子,它做的事情很相似。应该很容易适应您的需求..

        public partial class CrowdCodeService : ServiceBase
        {
            private Timer stateTimer;
            private TimerCallback timerDelegate;
            AutoResetEvent autoEvent = new AutoResetEvent(false);
    
            public CrowdCodeService()
            {
                InitializeComponent();
            }
            int secondsDefault = 30;
            int secondsIncrementError = 30;
            int secondesMaximum = 600;
            int seconds;
            protected override void OnStart(string[] args)
            {
                Loggy.Add("Starting CrowdCodeService.");
                timerDelegate = new TimerCallback(DoSomething);
                seconds = secondsDefault;
                stateTimer = new Timer(timerDelegate, autoEvent, 0, seconds * 1000);
            }
    
            static bool isRunning = false;
    
            // The state object is necessary for a TimerCallback.
            public void DoSomething(object stateObject)
            {
                if (CrowdCodeService.isRunning)
                {
                    return;
                }
                CrowdCodeService.isRunning = true;
                AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
                try
                {
    
                    ////// Do your work here
    
    
                    string cs = "Application";
                    EventLog elog = new EventLog();
                    if (!EventLog.SourceExists(cs))
                        {
                            EventLog.CreateEventSource(cs, cs);
                        }
                        elog.Source = cs;
                        elog.EnableRaisingEvents = true;
    
                        elog.WriteEntry("CrowdCodes Service Error:" + cmd.Message.ToString(), EventLogEntryType.Error, 991);
                    }
                }
                finally
                {    
                    CrowdCodeService.isRunning = false;
                }
    
            }
    
    
            protected override void OnStop()
            {
                Loggy.Add("Stopped CrowdCodeService.");
                stateTimer.Dispose();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2012-09-12
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多