Windows 服务如何以编程方式重新启动自身?

我需要在。NET 来启用 Windows 服务(Server2003)重新启动自身。这样做的最好方法是什么?有没有。NET API 来做吗?

128592 次浏览

我不认为您可以在一个自包含的服务(当您调用 Restart,它将停止服务,这将中断 Restart 命令,它将永远不会再次启动)。如果你能再加一个。Exe (一个使用 ServiceManager 类的控制台应用程序) ,然后您就可以开始独立的。并让它重新启动服务,然后退出。

转念一想,您可以让服务注册一个调度任务(例如,使用命令行‘ at’命令)来启动服务,然后让它自己停止; 这可能会奏效。

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

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

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

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

想象一辆汽车,当它启动时,它开始处于空闲状态,等待你的命令前进或后退。这还有其他好处,比如可以选择如何公开应用程序,从而实现更好的远程管理。

将服务设置为故障后重新启动(双击控制面板中的服务并查看这些选项卡——我忘记了它的名称)。然后,任何时候您想要重新启动服务,只需调用 Environment.Exit(1)(或任何非零返回值) ,操作系统将为您重新启动它。

这取决于您为什么希望它重新启动。

如果您只是在寻找一种定期清理服务本身的方法,那么您可以在服务中运行一个定时器,定期导致一个 purge 例程。

如果您正在寻找一种失败时重新启动的方法-服务主机本身可以在安装时提供这种能力。

那么,为什么需要重新启动服务器呢?

您可以使用 Windowscmd.exe创建一个子进程,重新启动自己:

 Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();

我将使用 Windows 计划程序来安排重新启动您的服务。问题是,你不能重新启动自己,但你可以停止自己。(你实际上已经锯掉了你所坐的树枝... ... 如果你明白我的类比的话)你需要一个独立的过程来为你做这件事。Windows 计划程序是合适的。安排一次性任务重新启动服务(甚至从服务本身内部)以立即执行。

否则,您将不得不创建一个“引导”过程来完成这项工作。

最简单的方法是创建一个批处理文件:

净停 净启动

并按照所需的时间间隔将文件添加到计划程序

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

对这个问题的第一个回答是最简单的解决方案: “环境。退出(1)”我在 Windows Server 2008 R2上使用这个,它非常好用。服务停止自己,O/S 等待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()

只是路过,我想我应该加一些额外的信息..。

您也可以抛出一个异常,这将自动关闭窗口服务,自动重新启动选项刚刚启动。唯一的问题是,如果你的电脑上有一个开发环境,然后 JIT 试图启动,你会得到一个提示说调试 Y/N 说不,然后它就会关闭,然后正确地重新启动。(在没有 JIT 的个人电脑上,一切正常)。 我之所以在找,是因为这个 JIT 是 Win 7的新产品(它曾经在 XP 等系统中很好的工作) ,我正在试图找到一种方法来禁用 JIT..。我可以试试环境。这里提到的退出方法也可以看看它是如何工作的。

英国,布里斯托尔

const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

其中 SERVICENAME是您的服务的名称(在服务名称中包含空格的双引号,否则可以省略)。

清除,无需自动重新启动配置。

创建一个像这样的 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%

创建一个单独的 appdomain 来承载应用程序代码。当需要重新启动时,我们可以卸载并重新加载 appdomain,而不是进程(windows service)。这就是 IIS 应用程序池的工作原理,它们不直接运行 asp.net 应用程序,它们使用单独的 appdmain。

支付到批处理文件或 EXE 的问题在于,服务可能拥有运行外部应用程序所需的权限,也可能没有。

我所发现的最干净的方法是使用 OnStop ()方法,它是服务控制管理器的入口点。然后,所有的清理代码都将运行,并且假设您的停止代码正在执行它的工作,那么您将不会有任何挂起的套接字或其他进程。

为此,您需要在终止之前设置一个标志,该标志告诉 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) { }
}