Windows 服务如何以编程方式自行重启?
我需要在 .NET 中编写可靠的代码,以使 Windows 服务(服务器 2003)能够自行重新启动。 最好的方法是什么? 有一些 .NET API 可以做到这一点吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我需要在 .NET 中编写可靠的代码,以使 Windows 服务(服务器 2003)能够自行重新启动。 最好的方法是什么? 有一些 .NET API 可以做到这一点吗?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(18)
将服务设置为在失败后重新启动(双击控制面板中的服务并查看这些选项卡 - 我忘记了它的名称)。 然后,只要您希望服务重新启动,只需调用
Environment.Exit(1)
(或任何非零返回),操作系统就会为您重新启动它。Set the service to restart after failure (double click the service in the control panel and have a look around on those tabs - I forget the name of it). Then, anytime you want the service to restart, just call
Environment.Exit(1)
(or any non-zero return) and the OS will restart it for you.您可以使用 Windows
cmd.exe
创建一个自行重新启动的子进程:You can create a subprocess using Windows
cmd.exe
that restarts yourself:您甚至无法确定运行服务的用户帐户是否有权停止和重新启动该服务。
You can't be sure that the user account that your service is running under even has permissions to stop and restart the service.
其中
SERVICENAME
是您的服务名称(包含双引号以解决服务名称中的空格,否则可以省略)。干净,无需自动重启配置。
where
SERVICENAME
is the name of your service (double quotes included to account for spaces in the service name, can be omitted otherwise).Clean, no auto-restart configuration necessary.
这取决于您希望它自行重启的原因。
如果您只是寻找一种让服务定期自行清理的方法,那么您可以在服务中运行一个计时器,定期引发清除例程。
如果您正在寻找一种在失败时重新启动的方法 - 服务主机本身可以在设置时提供该功能。
那么为什么需要重启服务器呢? 你想达到什么目的?
It would depend on why you want it to restart itself.
If you are just looking for a way to have the service clean itself out periodically then you could have a timer running in the service that periodically causes a purge routine.
If you are looking for a way to restart on failure - the service host itself can provide that ability when it is setup.
So why do you need to restart the server? What are you trying to achieve?
我不认为你可以在独立的服务中(当你调用重新启动时,它将停止服务,这将中断重新启动命令,并且它不会再次启动)。 如果您可以添加第二个 .exe(使用 ServiceManager 类的控制台应用程序),那么您可以启动独立的 .exe 并让它重新启动服务,然后退出。
再想一想,您可能可以让服务注册一个计划任务(例如,使用命令行“at”命令)来启动服务,然后让它自行停止; 那可能会起作用。
I don't think you can in a self-contained service (when you call Restart, it will stop the service, which will interrupt the Restart command, and it won't ever get started again). If you can add a second .exe (a Console app that uses the ServiceManager class), then you can kick off the standalone .exe and have it restart the service and then exit.
On second thought, you could probably have the service register a Scheduled Task (using the command-line 'at' command, for example) to start the service and then have it stop itself; that would probably work.
处理批处理文件或 EXE 的问题在于,服务可能具有也可能不具有运行外部应用程序所需的权限。
我发现最简洁的方法是使用 OnStop() 方法,它是服务控制管理器的入口点。 然后,所有清理代码都将运行,并且假设您的停止代码正在执行其工作,您将不会有任何挂起的套接字或其他进程。
为此,您需要在终止之前设置一个标志,告诉 OnStop 方法退出并显示错误代码; 那么SCM就知道该服务需要重新启动。 如果没有此标志,您将无法从 SCM 手动停止服务。 这还假设您已将服务设置为在出现错误时重新启动。
这是我的停止代码:
如果服务遇到问题并需要重新启动,我会启动一个线程来从 SCM 停止服务。 这允许服务自行清理:
The problem with shelling out to a batch file or EXE is that a service may or may not have the permissions required to run the external app.
The cleanest way to do this that I have found is to use the OnStop() method, which is the entry point for the Service Control Manager. Then all your cleanup code will run, and you won't have any hanging sockets or other processes, assuming your stop code is doing its job.
To do this you need to set a flag before you terminate that tells the OnStop method to exit with an error code; then the SCM knows that the service needs to be restarted. Without this flag you won't be able to stop the service manually from the SCM. This also assumes you have set up the service to restart on an error.
Here's my stop code:
If the service runs into a problem and needs to restart, I launch a thread that stops the service from the SCM. This allows the service to clean up after itself:
我将使用 Windows Scheduler 来安排服务的重新启动。 问题是你无法重新启动自己,但你可以阻止自己。 (你基本上已经锯掉了你坐的树枝......如果你明白我的类比)你需要一个单独的过程来为你做这件事。 Windows Scheduler 是一个合适的选择。 安排一项一次性任务来重新启动您的服务(甚至从服务本身内部)以立即执行。
否则,您将必须创建一个“引导”流程来为您完成这件事。
I would use the Windows Scheduler to schedule a restart of your service. The problem is that you can't restart yourself, but you can stop yourself. (You've essentially sawed off the branch that you're sitting on... if you get my analogy) You need a separate process to do it for you. The Windows Scheduler is an appropriate one. Schedule a one-time task to restart your service (even from within the service itself) to execute immediately.
Otherwise, you'll have to create a "shepherding" process that does it for you.
对这个问题的第一个回答是最简单的解决方案:“Environment.Exit(1)”我在 Windows Server 2008 R2 上使用它,它运行得很好。 服务自行停止,操作系统等待 1 分钟,然后重新启动。
The first response to the question is the simplest solution: "Environment.Exit(1)" I am using this on Windows Server 2008 R2 and it works perfectly. The service stops itself, the O/S waits 1 minute, then restarts it.
我认为不可以。 当服务“停止”时,它就会完全卸载。
好吧,我想总有办法的。 例如,您可以创建一个分离的进程来停止服务,然后重新启动它,然后退出。
I don't think it can. When a service is "stopped", it gets totally unloaded.
Well, OK, there's always a way I suppose. For instance, you could create a detached process to stop the service, then restart it, then exit.
只是路过:我想我会添加一些额外的信息...
你也可以抛出一个异常,这将自动关闭 Windows 服务,并且自动重新启动选项就会启动。唯一的问题是,如果你有在你的电脑上安装一个开发环境,然后 JIT 尝试启动,你会得到一个提示,提示“debug Y/N”。 说“不”,然后它将关闭,然后重新正常启动。 (在没有 JIT 的 PC 上一切正常)。
我的原因是这个 JIT 对于 Win 7 来说是新的(它曾经在 XP 等上工作得很好)并且我试图找到一种禁用 JIT 的方法....我可以尝试这里提到的 Environment.Exit 方法看看如何这也有效。
克里斯蒂安:英国布里斯托尔
Just passing: and thought i would add some extra info...
you can also throw an exception, this will auto close the windows service, and the auto re-start options just kick in. the only issue with this is that if you have a dev enviroment on your pc then the JIT tries to kick in, and you will get a prompt saying debug Y/N. say no and then it will close, and then re-start properly. (on a PC with no JIT it just all works).
the reason im trolling, is this JIT is new to Win 7 (it used to work fine with XP etc) and im trying to find a way of disabling the JIT.... i may try the Environment.Exit method mentioned here see how that works too.
Kristian : Bristol, UK
创建一个像这样的 restart.bat 文件
然后在 %service% 启动时删除任务 %taskname%
Create a restart.bat file like this
Then delete the task %taskname% when your %service% starts
创建一个单独的应用程序域来托管应用程序代码。 当需要重新启动时,我们可以卸载并重新加载应用程序域而不是进程(Windows 服务)。 这就是 IIS 应用程序池的工作方式,它们不直接运行 asp.net 应用程序,它们使用单独的 appdmain。
Create a separate appdomain to host the application code. When requires restart, we could unload and reload the appdomain instead the process (windows service). This is how IIS app pool works, they dont run asp.net app directly, they use separate appdmain.
使用
Process.Start
运行sc stop OwnServiceName
,然后运行 sc start OwnServiceName
仅当服务进程有权控制自身时才有效 - 它们总是不这样做。...即使服务进程确实有权限,只需运行 cmd.exe /c sc stop Self && sc start Self 不会工作,因为
sc stop
立即返回,而不等待服务停止(而旧的net stop
命令会等待,< a href="https://stackoverflow.com/questions/2874911/halt-batch-file-until-service-stop-is-complete#comment26512590_2874964">它不会无限期地等待)。 更好的方法是将这个多步骤逻辑放入.cmd
批处理文件中,并使用Process.Start( "cmd.exe", "/ c RestartService.cmd")
。至于确保服务有足够的权限自行重启:
如果您使用 WIX MSI 来安装 Windows 服务,则可以使用 WIX 的
util:PermissionEx
元素:如果您手动安装服务 - 或使用其他一些技术,然后您可以通过运行
sc sdset
设置服务权限,这需要熟悉 Windows 的 SDDL 语法 和 它与 Windows 服务安全性的关系。Windows 服务的默认 SDDL 似乎是这样的:
...使用这些定义:
...然后默认 SSDL 扩展为:
我们将
SU
规则更改为:因此,您可以从提升的进程(例如您的安装程序或服务安装程序):
...这意味着您的服务可以运行 Process.Start( "cmd.exe", "/c RestartService.cmd" )。
这就是我的
RestartService.cmd
的样子:(感谢此处发布的 @js2010 的答案 )
Using
Process.Start
to runsc stop OwnServiceName
followed bysc start OwnServiceName
only works when the service-process has permission to control itself - which they invariably don't....and even if the service-process does have permission, simply running
cmd.exe /c sc stop Self && sc start Self
isn't going to work becausesc stop
returns immediately without waiting for the service to stop (while the oldernet stop
command does wait, it doesn't wait indefinitely). A better approach is to put this multi-step logic in a.cmd
batch file and run that withProcess.Start( "cmd.exe", "/c RestartService.cmd" )
.As for ensuring the Service has sufficient permission to restart itself:
If you used WIX MSI to install the Windows Service, you can use WIX's
util:PermissionEx
element:If you're manually installing your service - or using some other technique, then you can set service permissions by running
sc sdset
, which requires familiarizing yourself with Windows' SDDL syntax and how it relates to Windows Service security.The default SDDL for a Windows Service seems to be this:
...using these definitions:
...then the default SSDL expands to this:
We change the
SU
rule to this:So you run this from an elevated process (e.g. your setup program or service-installer):
...which then means your service can run
Process.Start( "cmd.exe", "/c RestartService.cmd" )
.This is what my
RestartService.cmd
looks like:(With acknowledgement to @js2010's answer posted here)
更好的方法可能是利用 NT 服务作为应用程序的包装器。 当 NT 服务启动时,您的应用程序可以以“空闲”模式启动,等待命令启动(或配置为自动启动)。
想象一辆汽车,当它启动时,它开始处于空闲状态,等待您的前进或后退命令。 这还带来了其他好处,例如更好的远程管理,因为您可以选择如何公开您的应用程序。
The better approach may be to utilize the NT Service as a wrapper for your application. When the NT Service is started, your application can start in an "idle" mode waiting for the command to start (or be configured to start automatically).
Think of a car, when it's started it begins in an idle state, waiting for your command to go forward or reverse. This also allows for other benefits, such as better remote administration as you can choose how to expose your application.
最简单的方法是有一个批处理文件:
net stop
net start
并将文件添加到您所需的时间间隔的调度程序中
The easiest way is to have a batch file with:
net stop
net start
and add the file to the scheduler with your desired time interval