我开发了windows服务,用于每隔两分钟检查一些服务是否运行。如果服务未运行,则自动启动它们。
这是我的代码
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.CheckServices();
this.ScheduleService();
}
protected override void OnStop()
{
this.Schedular.Dispose();
}
public void CheckServices()
{
log4net.Config.BasicConfigurator.Configure();
log4net.ILog log = log4net.LogManager.GetLogger(typeof(Service1));
try
{
string[] arr1 = new string[] { "CaseWorksCachingService", "Te.Service" };
for (int i = 0; i < arr1.Length; i++)
{
ServiceController service = new ServiceController(arr1[i]);
service.Refresh();
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
}
}
}
catch (Exception ex)
{
log.Error("Error Message: " + ex.Message.ToString(), ex);
}
}
//ScheduleService Method
private Timer Schedular;
public void ScheduleService()
{
try
{
Schedular = new Timer(new TimerCallback(SchedularCallback));
string mode = ConfigurationManager.AppSettings["Mode"].ToUpper();
//Set the Default Time.
DateTime scheduledTime = DateTime.MinValue;
if (mode.ToUpper() == "INTERVAL")
{
//Get the Interval in Minutes from AppSettings.
int intervalMinutes = Convert.ToInt32(ConfigurationManager.AppSettings["IntervalMinutes"]);
//Set the Scheduled Time by adding the Interval to Current Time.
scheduledTime = DateTime.Now.AddMinutes(intervalMinutes);
if (DateTime.Now > scheduledTime)
{
//If Scheduled Time is passed set Schedule for the next Interval.
scheduledTime = scheduledTime.AddMinutes(intervalMinutes);
}
}
TimeSpan timeSpan = scheduledTime.Subtract(DateTime.Now);
//Get the difference in Minutes between the Scheduled and Current Time.
int dueTime = Convert.ToInt32(timeSpan.TotalMilliseconds);
//Change the Timer's Due Time.
Schedular.Change(dueTime, Timeout.Infinite);
}
catch (Exception ex)
{
//Stop the Windows Service.
using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("MyFirstService"))
{
serviceController.Stop();
}
}
}
private void SchedularCallback(object e)
{
//this.WriteToFile("Simple Service Log: {0}");
this.CheckServices();
this.ScheduleService();
}
}
这是我的app.config档案
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key ="Mode" value ="Interval"/>
<!-- <add key ="Mode" value ="Interval"/>-->
<add key ="IntervalMinutes" value ="2"/>
</appSettings>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=2.0.5, Culture=neutral, PublicKeyToken=1b44e1d426115821" />
</configSections>
<!-- Log4net Logging Setup -->
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
<file value="C:\\mylogfile1.txt" />
<!-- the location where the log file would be created -->
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
</configuration>
错误:“本地计算机上的Windows Search服务已启动,然后停止。如果其他服务或程序未使用某些服务,则会自动停止。”
您的服务的问题正是Matt Davis在回答中所说的:只有在启动时产生了前台线程,服务才会保持运行。这就是他的代码所做的。它只创建了一个线程,该线程基本上什么都不做,只是等待,但这足以保持服务运行。
除了一件事之外,其余代码可以保持不变。按如下方式更改ScheduleService方法:
public void ScheduleService()
{
try
{
// Only create timer once
if (Schedular != null)
Schedular = new Timer(new TimerCallback(SchedularCallback));
// Use proper way to get setting
string mode = Properties.Settings.Default.Mode.ToUpper();
...
if (mode == "INTERVAL")
{
// Use proper way to get settings
int intervalMinutes = Properties.Settings.Default.IntervalMinutes;
...
我知道有些人可能不认为这是一个答案,但调试似乎是这里的关键,因此我将告诉你我找到了一种调试服务的简单方法。
步骤1
使用两种方法扩展您的服务:一种调用OnStart
,一种调用OnStop
,因为默认方法受到保护。
public void DoStart(string[] args)
{
OnStart(xyz);
}
public void DoStop()
{
OnStop();
}
第2步
添加一个简单的GUI。没有任何控件的WinForms表单就足够了。扩展构造函数以获取您的服务类的实例。当表单加载“启动您的服务”时,当它关闭时,“停止您的服务”。根据您创建表单的方式,您可能需要手动引用System. Windows. Forms
和System. Drawing
在您的项目中。
例子:
public class ServiceGUI : System.Windows.Forms.Form
{
private MyService _myService;
public ServiceGUI(MyService service)
{
_myService = service;
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
_myService.DoStart(null);
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
_myService.DoStop();
}
}
步骤3
让您的Main
方法决定是作为服务运行还是作为GUI应用程序运行。方便的环境。UserInteractive
属性允许您决定exe是否由某些GUI用户运行。
if (Environment.UserInteractive)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ServiceGUI(new MyService()));
}
else
{
ServiceBase.Run(new ServiceBase[] { new MyService() });
}
你现在能做什么
你可以像启动普通应用程序一样启动应用程序,并实际正确调试、设置断点、检查变量等。当然,我知道你也可以将调试器附加到正在运行的进程,但在你的情况下,你没有正在运行的进程,因此这是一个很好的解决方案,可以了解问题所在。
像服务启动代码之类的东西可能不起作用(除非您以管理员身份运行Visual Studio),但这也可以很好地测试在启动服务时遇到错误时是否起作用。
很可能会发生异常,导致服务过早退出。这是值得研究的。然而,我怀疑问题的实际原因是,您的服务只是在执行OnStart()方法后立即退出。Windows服务不会自动保持运行。如果OnStart()方法没有启动保持服务运行的前台线程,您将看到收到的确切错误。我尝试在本地控制台应用程序中执行您的代码,一旦方法完成,控制台应用程序就会退出。
要使您的服务保持运行直到关闭,请在
OnStart()
方法中启动前台线程。以下是一个工作示例。
using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThreadFunc);
_thread.Name = "My Worker Thread";
_thread.IsBackground = false;
_thread.Start();
}
protected override void OnStop()
{
this.Schedular.Dispose();
this._shutdownEvent.Set();
this._thread.Join(3000);
}
private void WorkerThreadFunc()
{
this.CheckServices();
this.ScheduleService();
// This while loop will continue to run, keeping the thread alive,
// until the OnStop() method is called.
while (!_shutdownEvent.WaitOne(0))
{
Thread.Sleep(1000);
}
}
其他什么都不需要改变。
若你们想调试你们的服务,调用系统。诊断。调试器。在方法的开头启动()并在调试中编译。启动服务时,系统将提示您启动调试会话。假设您在机器上有足够的权限,您应该能够设置断点并在此时正常调试。
HTH
我正在迁移我的Android应用程序,目标是Android奥利奥。我正在运行一个服务,它应该无限期运行,以执行一个特定的任务。
问题内容: 我已经使用servlet和JSP开发了一个Web应用程序。我本身并没有使用任何框架,而是使用了自己的自制MVC框架。我正在使用MySQL作为后端。 我要执行以下操作: 每小时清理一次数据库中的一些数据 每隔15分钟在XML文件中的某处生成并存储有关数据的统计信息 问题是:当前,我的所有代码都是作为从客户端收到的请求而运行的。 如何在服务器端运行定期任务? 我现在有一个解决方案是在控制器
我只是尝试使用协议缓冲区为Go语言生成代码。但是无法使用原型命令生成服务。 上面是一个虚拟的原型文件,我试图将其转换为Go语言。但是无法生成正确的文件,因为在我的系统中,它无法将行识别为服务。 我正在windows系统上使用以下版本的protoc: 使用以下命令生成代码: \greet\greetpb\greet.proto--go_out=。 下面是由上述命令生成的go代码: 在以后的go代码中
当我启动start WebLogic.cmd在mydomed\bin中时,我的服务器正常工作。当我注销时,它会自动停止。在这里,我试图创建一个窗口服务,如oracle文档“http://docs.oracle.com/cd/E11035_01/wls100/server_start/winservice.html”中所述。 但我的服务不再说这与此无关。 这是我创建的2个文件 1.)run.cmdD
我的要求是 Android应用程序必须发送用户位置详细信息(纬度 我采用的方法是使用报警管理器,我以配置的间隔调用我的服务,无论应用程序是否正在运行,它都将向服务器发送位置详细信息。 这是一个好方法吗?
问题内容: 我遇到了一个非常奇怪的问题。我需要在Jenkins中配置代理,以便 能够访问其中一项作业的SVN存储库。我这样做有两种方式: 从命令行使用必需的参数启动Jenkins 在jenkins.xml文件中定义参数时,将Jenkins作为Windows服务启动。 Starting from command line : -Dhudson.model.DirectoryBrowserSuppor