简体   繁体   English

检查Windows服务是否已被强制关闭或崩溃

[英]Check if windows service has been forcefully shut down or crashed

I have a windows service written in C# .NET framework 3.5 and would like to know the best way to check if previous shutdown of a service was regular. 我有一个用C#.NET Framework 3.5编写的Windows服务,并且想知道检查服务以前关闭是否正常的最佳方法。

Upon starting the service, there should be a check if the last shutdown was regular (via stop service button in services management) or if somebody just killed the process (or it crashed for some reason not directly linked to the service itself). 启动服务后,应检查上次关闭是否正常(通过服务管理中的“停止服务”按钮)或是否有人刚刚终止了该进程(或由于某种原因导致崩溃而未直接链接到服务本身)。

I thought about writing encrypted XML on a hard drive upon starting a service, and then editing it with some values when service is being stopped. 我考虑过在启动服务时在硬盘上写入加密的XML,然后在停止服务时使用一些值对其进行编辑。 In that way, after I start the service again next time, I could check the XML and see if the values were edited in correct way during shutdown, and if they were not I'd know the process was killed or it crashed. 这样,下一次再次启动服务后,我可以检查XML并查看关闭期间是否以正确的方式对值进行了编辑,如果不是,我将知道进程已终止或崩溃。

This way seems too unreliable and not a good practice. 这种方法似乎不太可靠,也不是一个好的做法。 What do you suggest? 你有什么建议?

Clarification: What the service does is it sits on a server and listens to connections from client machines. 说明:服务的作用是它位于服务器上,并侦听来自客户端计算机的连接。 Once the connection has been established, it communicates to a remote database via web services and determines whether they have right to connect (and therefore use application that is the caller). 建立连接后,它将通过Web服务与远程数据库进行通信,并确定它们是否有权连接(并因此使用作为调用方的应用程序)。 One of the aspects of protection is concurrency check, and if I have a limit set to 5 work stations, I keep the TcpClient connection alive from windows service to, let's say 5 workstations, and the sixth one cannot connect. 保护的方面之一是并发检查,如果我将限制设置为5个工作站,则我将TcpClient连接保持从Windows服务到例如5个工作站的活动状态,而第6个工作站无法连接。

If I kill the service process and restart it, the connections are gone and I have 5 "licensed" apps running on workstations, and now there are 5 free connection slots to be taken by 5 more. 如果我终止服务进程并重新启动它,则连接消失了,并且在工作站上运行了5个“许可”应用程序,现在有5个空闲连接插槽可供5个以上的空闲插槽使用。

I also cant see anything bad using a file. 我也看不到任何使用文件的错误。 You could even use this file to log some more information. 您甚至可以使用此文件来记录更多信息。

Eg. 例如。 you could attach to the AppDomains Unhanded Exception event and try to log that exception. 您可以附加到AppDomains Unhanded Exception事件并尝试记录该异常。 Or you could evaluate how log your service has been running/not running (parsing a logfile for that task is a little bit harder). 或者,您可以评估服务运行/未运行日志的方式(为该任务解析日志文件会有点困难)。

Of course - this is not an excuse for not using logfiles. 当然-这不是不使用日志文件的借口。

I went with this in the end: Service used to check up on the connected workstations to see if they're alive, but now I've built in periodical check from all the workstations as well (they connect through a common router dll where I've built in the check). 最后,我进行了以下处理:该服务用于检查已连接的工作站是否存在,但是现在我还从所有工作站中进行了定期检查(它们通过一个公用路由器dll连接,已在支票中建立)。 Every 10 seconds the connection is verified, and if there is none, the client will try to reconnect in 15 seconds, which will be successful if there was just a temporary network problem, but will fail if the service was shut down forcefully (since all it's Tcp objects will be lost). 每隔10秒钟验证一次连接,如果没有连接,客户端将尝试在15秒钟内重新连接,如果只是暂时的网络问题,它将成功,但是如果强制关闭服务,则失败(因为所有它的Tcp对象将丢失)。

I would suggest to use the EventLog . 我建议使用EventLog Add a log event when a service start or stops and read through the event logs to detect anomalies. 在服务启动或停止时添加日志事件,并通读事件日志以检测异常。

Here's a basic sample from CodeProject . 这是CodeProject的基本示例。 Here's a walkthrough from MSDN how to create/delete/read event logs and entries. 这是MSDN演练,介绍如何创建/删除/读取事件日志和条目。

Unless the service is running some sort securiy system that you need to have a "tamper" proof system i dont see why using a file is a bad solution. 除非服务正在运行某种需要安全的“防篡改”系统的安全系统,否则我不明白为什么使用文件不是一个好的解决方案。

Personaly i think a encrpted xml file is overkill, a simple text file should be enough. 就个人而言,我认为加密的xml文件是多余的,一个简单的文本文件就足够了。

I think you are on the right track, I'm not sure why you want to edit the values, just use the file (or a registry key) as a marker to indicate that the service was started and is running. 我认为您走在正确的道路上,我不确定为什么要编辑这些值,仅使用文件(或注册表项)作为标记来指示该服务已启动并正在运行。 During a graceful shutdown remove the marker. 在正常关机期间,删除标记。 You then just need to look for the existence of the marker to know whether you were shutdown gracefully or crashed. 然后,您只需要查找标记的存在即可知道您是正常关闭还是崩溃。

If you are finding that the file isn't created reliably, then make sure you are closing and flushing and disposing of the file object rather than relying on the garbage collector. 如果发现文件创建不可靠,请确保关闭,刷新和处置文件对象,而不要依赖垃圾回收器。

--- EDIT following clarification --- ---澄清后进行编辑---

So the requirement is for a licensing system and not simply to determine if the service was shutdown gracefully. 因此,要求的是许可系统,而不仅仅是确定服务是否正常关闭。 I'm guessing that the desire is for the 'licenses' to be cleared on a graceful shutdown and restored following a crash, the scenarios are interchangeable. 我猜想是希望在正常关闭时清除“许可证”并在崩溃后将其还原,这种情况是可以互换的。

I would probably use a database backing store, with suitable security, to hold the license keys at the server. 我可能会使用具有适当安全性的数据库后备存储来将许可证密钥保存在服务器上。 As each client connects and requests a license they are provided with a key that has to be presented for each communication from the client. 当每个客户端连接并请求许可证时,将为它们提供一个密钥,该密钥必须针对客户端的每次通信提供。 The server is obviously verifying that the presented key is valid for the current session. 服务器显然正在验证所提供的密钥对当前会话有效。 Should the server be gracefully shutdown it can clear the key table, if it crashes then the keys would still be present and can be honoured. 如果服务器正常关闭,则可以清除密钥表,如果崩溃,则密钥仍然存在并且可以兑现。 That's probably the simplest approach I can think of that's secure. 我认为这可能是最安全的最简单方法。

If there's yet more to the story then let us know. 如果故事还有更多内容,请告诉我们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM