一个Windows服务如何以编程方式重启自己?
我需要在.NET中编写健壮的代码,以使Windows服务(服务器2003)能够自行重启。 这样做的最好方法是什么? 有一些.NET API来做到这一点?
将服务设置为在失败后重新启动(双击控制面板中的服务并查看这些选项卡 – 我忘记了它的名称)。 然后,只要你想重启服务,只要调用Environment.Exit(1)
(或任何非零返回值),操作系统就会为你重启。
Dim proc As New Process() Dim psi As New ProcessStartInfo() psi.CreateNoWindow = True psi.FileName = "cmd.exe" psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE" psi.LoadUserProfile = False psi.UseShellExecute = False psi.WindowStyle = ProcessWindowStyle.Hidden proc.StartInfo = psi proc.Start()
您无法确定您的服务正在运行的用户帐户是否有权停止并重新启动服务。
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\""; Process.Start("CMD.exe", strCmdText);
其中SERVICENAME
是您的服务的名称(包含双引号以说明服务名称中的空格,否则可以省略)。
清理,不需要自动重新启动configuration。
这将取决于你为什么要重启自己。
如果您只是想要定期清理服务,那么您可以在服务中定期运行定时清理程序。
如果您正在寻找一种在失败时重新启动的方式 – 服务主机本身可以在安装时提供该function。
那么为什么你需要重新启动服务器? 你想达到什么目的?
您可以创build一个进程,该进程是重新启动自己的DOS命令提示符:
Process process = new Process(); process.StartInfo.FileName = "cmd"; process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\""; process.Start();
我不认为你可以在一个独立的服务(当你打电话重启,它会停止服务,这将中断重启命令,它不会再次开始)。 如果您可以添加第二个.exe(一个使用ServiceManager类的控制台应用程序),那么您可以启动独立的.exe,并重新启动服务,然后退出。
第二个想法是,你可以让这个服务注册一个Scheduled Task(例如使用'at'命令的命令行)来启动服务,然后让它自己停止; 这可能会奏效。
我将使用Windows计划程序来安排重新启动您的服务。 问题是你不能重新启动自己,但你可以阻止自己。 (你基本上已经看到了你正在坐的分支…如果你有我的类比)你需要一个单独的过程来为你做。 Windows计划程序是一个合适的。 安排一次性任务重新启动您的服务(即使在服务本身内)立即执行。
否则,你将不得不创build一个“牧养”的过程,为你做。
对batch file或EXE进行脱壳的问题是,服务可能具有或不具有运行外部应用程序所需的权限。
最简单的方法是使用OnStop()方法,它是服务控制pipe理器的入口点。 然后,所有清理代码都会运行,假设您的停止代码正在完成工作,您将不会有任何挂起的套接字或其他进程。
要做到这一点,您需要在终止之前设置一个标志,告诉OnStop方法退出并显示错误代码; 那么SCM知道该服务需要重新启动。 没有这个标志,你将无法从SCM手动停止服务。 这也假定你已经设置了服务来重新启动一个错误。
这是我的停止代码:
... bool ABORT; protected override void OnStop() { Logger.log("Stopping service"); WorkThreadRun = false; WorkThread.Join(); Logger.stop(); // if there was a problem, set an exit error code // so the service manager will restart this if(ABORT)Environment.Exit(1); }
如果服务遇到问题并需要重新启动,我会启动一个线程来停止SCM的服务。 这允许服务自行清理:
... if(NeedToRestart) { ABORT = true; new Thread(RestartThread).Start(); } void RestartThread() { ServiceController sc = new ServiceController(ServiceName); try { sc.Stop(); } catch (Exception) { } }
我不认为它可以。 当一个服务“停止”,它完全卸载。
那好吧,总有一种我想的办法。 例如,您可以创build一个分离的进程来停止服务,然后重新启动,然后退出。
对这个问题的第一个回答是最简单的解决scheme:“Environment.Exit(1)”我在Windows Server 2008 R2上使用它,它完美的工作。 服务自行停止,O / S等待1分钟,然后重新启动。
创build一个单独的应用程序域以承载应用程序代码。 当需要重新启动时,我们可以卸载并重新加载appdomain,而不是进程(Windows服务)。 这是IIS应用程序池如何工作,他们不直接运行asp.net应用程序,他们使用单独的appdmain。
更好的方法可能是使用NT服务作为您的应用程序的包装。 当NT服务启动时,您的应用程序可以以“空闲”模式启动,等待命令启动(或configuration为自动启动)。
想想一辆汽车,它开始时会在空闲状态下开始,等待你的命令前进或后退。 这还允许其他好处,比如更好的远程pipe理,因为您可以select如何公开您的应用程序。
只是通过:我以为我会添加一些额外的信息…
你也可以抛出一个exception,这将自动closuresWindows服务,并自动重新启动选项刚刚踢。唯一的问题是,如果你有你的电脑开发环境,然后JIT试图踢,你会得到一个提示说debuggingY / N。 说不,然后它会closures,然后重新正常启动。 (在没有JIT的PC上,它只是所有的作品)。 原因即时通讯,这是JIT是新的赢7(它曾经与XP等工作正常),即时通讯试图find一种方法禁用JIT ….我可以尝试这里提到的Environment.Exit方法看看如何那也行。
克里斯蒂安:英国布里斯托尔
像这样创build一个restart.bat文件
@echo on set once="C:\Program Files\MyService\once.bat" set taskname=Restart_MyService set service=MyService echo rem %time% >%once% echo net stop %service% >>%once% echo net start %service% >>%once% echo del %once% >>%once% schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z schtasks /run /tn %taskname%
然后在%service%启动时删除任务%taskname%
nssm非常棒。 它会为你做这一切
最简单的方法是有一个batch file:
净停止净开始
并将文件添加到调度程序与您所需的时间间隔
private static void RestartService(string serviceName) { using (var controller = new ServiceController(serviceName)) { controller.Stop(); int counter = 0; while (controller.Status != ServiceControllerStatus.Stopped) { Thread.Sleep(100); controller.Refresh(); counter++; if (counter > 1000) { throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName)); } } controller.Start(); } }