Answers:
更新:
我的原始答案将近四年之后,这个答案已经过时了。自TopShelf以来出现,Windows Services的开发就变得容易了。现在,您只需要弄清楚如何支持故障转移...
原始答案:
我真的不是Windows Scheduler的粉丝。用户密码必须作为@moodforall提供上面指出的,当有人更改该用户的密码时,这很有趣。
Windows Scheduler的另一个主要烦人之处是它以交互方式运行,而不是作为后台进程运行。在RDP会话中每20分钟弹出15个MS-DOS窗口时,您会踢自己没有安装为Windows服务的窗口。
无论您选择什么,我当然都建议您将处理代码从控制台应用程序或Windows服务中分离到不同的组件中。然后,您可以选择从控制台应用程序调用工作进程并将其挂接到Windows Scheduler,或者使用Windows服务。
您会发现安排Windows服务并不好玩。一个相当普遍的情况是您有一个长期运行的进程,希望定期运行。但是,如果您正在处理队列,那么您实际上不希望同一工作人员的两个实例处理同一队列。因此,您需要管理计时器,以确保长时间运行的进程是否运行的时间超过了指定的计时器间隔,直到现有进程完成后,它才会再次启动。
在写完所有这些之后,您会认为,为什么我不只是使用Thread.Sleep?这使我可以让当前线程继续运行,直到完成为止,然后暂停间隔开始,线程进入睡眠状态,并在需要的时间后再次启动。整齐!
然后,您会与许多专家一起阅读Internet上的所有建议,告诉您这实际上是一种不良的编程习惯:
因此,您会挠头思考,WTF,撤消待处理的结帐->是的,我确定->撤消今天的所有工作.....该死,该死,该死...。
但是,即使每个人都认为这很糟糕,我还是喜欢这种模式:
OnStart方法为单线程方法。
protected override void OnStart (string args) { // Create worker thread; this will invoke the WorkerFunction // when we start it. // Since we use a separate worker thread, the main service // thread will return quickly, telling Windows that service has started ThreadStart st = new ThreadStart(WorkerFunction); workerThread = new Thread(st); // set flag to indicate worker thread is active serviceStarted = true; // start the thread workerThread.Start(); }
该代码实例化了一个单独的线程,并将我们的辅助函数附加到该线程。然后,它启动线程并让OnStart事件完成,以使Windows认为该服务未挂起。
单线程方法的辅助方法。
/// <summary> /// This function will do all the work /// Once it is done with its tasks, it will be suspended for some time; /// it will continue to repeat this until the service is stopped /// </summary> private void WorkerFunction() { // start an endless loop; loop will abort only when "serviceStarted" // flag = false while (serviceStarted) { // do something // exception handling omitted here for simplicity EventLog.WriteEntry("Service working", System.Diagnostics.EventLogEntryType.Information); // yield if (serviceStarted) { Thread.Sleep(new TimeSpan(0, interval, 0)); } } // time to end the thread Thread.CurrentThread.Abort(); }
OnStop方法为单线程方法。
protected override void OnStop() { // flag to tell the worker process to stop serviceStarted = false; // give it a little time to finish any pending work workerThread.Join(new TimeSpan(0,2,0)); }
来源:http : //tutorials.csharp-online.net/Creating_a_.NET_Windows_Service%E2%80%94Alternative_1%3a_Use_a_Separate_Thread (无效链接)
多年来,我一直在运行许多类似的Windows服务,并且对我有用。我仍然没有看到人们同意的推荐模式。做适合您的事情。
NT AUTHORITY\NetworkService
是一个具有有限权限的帐户。
这里有些错误信息。Windows Scheduler完全能够在后台运行任务,而无需弹出窗口且不需要密码。在NT AUTHORITY \ SYSTEM帐户下运行它。使用此schtasks开关:
/ ru系统
但是可以,对于访问网络资源,最佳实践是具有单独的未过期密码策略的服务帐户。
编辑
根据您的操作系统和任务本身的要求,使用该/ru
选项,您可能可以使用特权比本地系统少的帐户。
从精美的手册中
/RU username
A value that specifies the user context under which the task runs.
For the system account, valid values are "", "NT AUTHORITY\SYSTEM", or "SYSTEM".
For Task Scheduler 2.0 tasks, "NT AUTHORITY\LOCALSERVICE", and
"NT AUTHORITY\NETWORKSERVICE" are also valid values.
Vista和Server 2008中提供了Task Scheduler 2.0。
在XP和Server 2003中,system
是唯一的选择。
Local Service
(aka NT AUTHORITY\LocalService
)而不是LocalSystem
(aka .\LocalSystem
)的身份运行。前者具有有限的权利,而后者是管理员
LocalService
,并NetworkService
在可schtasks
V2 Vista的开始,并应优先在可能的情况。当时,这是指schtasks
XP和Server 2003中System
的版本,根据旧版本手册technet.microsoft.com/zh-cn/library/bb490996.aspx
在.NET开发中,我通常从开发控制台应用程序开始,该应用程序将运行并将所有日志记录输出到控制台窗口。但是,当它与command参数一起运行时,这只是一个控制台应用程序/console
。如果不使用此参数运行它,它将充当Windows服务,它将继续在我自己的自定义编码计划计时器上运行。
我认为Windows服务通常用于管理其他应用程序,而不是长期运行的应用程序。或..它们正在不断运行重量级应用程序,例如SQL Server,BizTalk,RPC连接,IIS(即使IIS从技术上讲将工作分担到其他进程)。
就个人而言,相对于Window Services,我更喜欢预定的任务来执行重复性维护任务和应用程序,例如文件复制/同步,批量电子邮件发送,文件的删除或归档,数据校正(在其他解决方法不可用时)。
对于一个项目,我参与了8或9 Windows服务的开发,但这些服务位于内存中,处于空闲状态,每个实例占用20MB或更多内存。计划任务将完成其任务,并立即释放内存。
“服务”一词与“服务”有共同之处。预计它将始终运行并“服务”。任务就是任务。
角色扮演。如果我是另一个操作系统,应用程序或设备,并且我调用了服务,那么我希望它正在运行,并且希望得到响应。如果我(操作系统,应用程序,开发人员)只需要执行一个隔离的任务,那么我将执行一个任务,但是如果我希望进行通信(可能是双向通信),则需要一个服务。这与最有效的方式有关,以便使两件事进行通信,或者使一件事情要执行单个任务。
然后是调度方面。如果您希望某些内容在特定时间运行,请安排时间表。如果您不知道何时需要它,或者“即时”需要它,请服务。
我的反应本质上是更具哲学性的,因为这与人类如何与他人互动和合作非常相似。我们越了解交流的技巧,“实体”越了解它们的作用,这个决定就越容易。
抛开所有哲学,当您像我的IT部门经常做的那样“快速制作原型”时,您将尽一切努力来维持生计。一旦原型设计和概念证明不可行,通常是在早期计划和发现中,您就必须确定对于长期可持续性而言更可靠的方法。
好的,总而言之,它高度依赖于许多因素,但是希望这能提供见解而不是造成混淆。
Windows服务不需要任何人登录,Windows具有停止,启动和记录服务结果的功能。
预定任务不需要您学习如何编写Windows服务。
NT AUTHORITY\LocalService
或NT AUTHORITY\NetworkService
)。因为帐户没有密码,所以提供的任何密码都会被忽略。
Why not provide both?
In the past I've put the 'core' bits in a library and wrapped a call to Whatever.GoGoGo() in both a service as well as a console app.
对于某些您每两分钟触发一次的事件,它的作用并不大(例如,只是一个“ ping”类型的函数)。包装程序不必只包含一个方法调用和一些日志记录。
这是一个古老的问题,但我想分享一下我所面临的。
最近,我被要求捕获雷达的屏幕截图(从气象网站获取)并每10分钟将其保存在服务器中一次。
这需要我使用WebBrowser。我通常会提供Windows服务,因此我决定也提供这一服务,但它会继续崩溃。这是我在事件查看器中看到的 错误”模块路径中:C:\ Windows \ system32 \ MSHTML.dll
Since the task was urgent and I had very less time to research and experiment, I decided to use a simple console application and triggered it as a task and it executed smoothly.
I really liked the article by Jon Galloway recommended in accepted answer by Mark Ransom.
Recently passwords on the servers were changed without acknowledging me and all the services failed to execute since they could not logon. So ppl claiming in the article comments that this is a problem. I think windows services can face same problem (Pls. correct me if I am wrong, I am jus a newbie)
另外提到的事情,如果使用任务计划程序窗口弹出或控制台窗口弹出。我从来没有面对过。它可能会弹出,但至少是瞬时的。
通常,核心信息是并且应该是代码本身必须对每个“触发器/客户端”都可执行。因此,从一种方法切换到另一种方法不应该是火箭科学。
In the past we used more or less always Windows Services but since also more and more of our customers switch to Azure step by step and the swap from a Console App (deployed as a Scheduled Task) to a WebJob in Azure is much easier than from a Windows Service, we focus on Scheduled Tasks for now. If we run into limitations, we just ramp up the Windows Service project and call the same logic from there (as long as customers are working OnPrem..) :)
BR, y
Windows services want more patience until it's done. It has a bit hard debug and install. It's faceless. If you need a task which must be done in every second, minute or hour, you should choice Windows Service.
Scheduled Task is quickly developed and has a face. If you need a daily or weekly task, you can use Scheduled Task.