142

我需要在 .NET 中编写健壮的代码以使 Windows 服务(服务器 2003)能够自行重新启动。最好的方法是什么?是否有一些 .NET API 可以做到这一点?

4

17 回答 17

200

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.

于 2008-10-21T00:58:35.740 回答
23
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()
于 2011-05-31T05:26:55.400 回答
18

您甚至无法确定运行您的服务的用户帐户是否有权停止和重新启动服务。

于 2008-10-21T00:19:27.300 回答
14
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

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.

于 2013-04-12T14:10:25.403 回答
13

You can create a subprocess using Windows cmd.exe that restarts yourself:

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();
于 2009-02-11T21:13:04.030 回答
5

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?

于 2008-10-21T01:02:17.510 回答
4

我不认为你可以在一个独立的服务中(当你调用 Restart 时,它会停止服务,这会中断 Restart 命令,并且永远不会再次启动)。如果您可以添加第二个 .exe(使用 ServiceManager 类的控制台应用程序),那么您可以启动独立 .exe 并让它重新启动服务然后退出。

再想一想,您可能会让服务注册一个计划任务(例如,使用命令行“at”命令)来启动服务,然后让它自行停止;那可能会奏效。

于 2008-10-21T00:18:03.777 回答
3

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:

...

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);
}

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:

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}
于 2016-04-27T15:23:53.897 回答
2

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.

于 2009-03-03T17:23:41.250 回答
2

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.

于 2010-11-12T03:48:19.870 回答
1

我不认为它可以。当服务“停止”时,它会完全卸载。

好吧,好吧,我想总有办法。例如,您可以创建一个分离的进程来停止服务,然后重新启动它,然后退出。

于 2008-10-21T00:18:07.567 回答
0

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

于 2011-08-09T09:30:28.710 回答
0

Create a restart.bat file like this

@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%

Then delete the task %taskname% when your %service% starts

于 2014-08-14T09:02:24.663 回答
0

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.

于 2015-07-13T09:54:19.733 回答
-1

更好的方法可能是使用 NT 服务作为应用程序的包装器。当 NT 服务启动时,您的应用程序可以以“空闲”模式启动,等待命令启动(或配置为自动启动)。

想象一辆车,当它启动时,它开始处于空闲状态,等待您的命令前进或后退。这也带来了其他好处,例如更好的远程管理,因为您可以选择如何公开您的应用程序。

于 2008-10-21T00:40:29.537 回答
-2

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

于 2009-06-11T04:52:33.013 回答
-3
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();
        }
    }
于 2010-10-12T15:39:39.007 回答