在服务停止完成之前暂停批处理文件?

Posted

技术标签:

【中文标题】在服务停止完成之前暂停批处理文件?【英文标题】:Halt batch file until service stop is complete? 【发布时间】:2010-05-20 14:54:27 【问题描述】:

我正在使用批处理文件来停止 Windows 服务。我正在使用sc 命令,但鉴于以下问题,我对其他想法持开放态度。问题是批处理文件继续服务正在停止(scstop 参数似乎只是请求停止 - 它没有等待停止)。

如何将批处理文件修改为不继续直到停止完成

【问题讨论】:

【参考方案1】:

您可以使用NET stop,它是同步的,即它会一直等到服务停止。

看 - NET stop

【讨论】:

但是,如果服务已经停止,net stop 将抛出一般错误代码 2(拒绝访问)。 这并不完全正确。如果服务需要 4 分钟才能真正完全停止并退出,“net stop”命令将在 20-40 秒后返回,但服务进程尚未终止。它返回“无法停止服务”......但这具有误导性。服务已被发送停止命令,但在 SCM 超时内还没有完全退出。 我知道这个线程很旧,但我刚刚在 Windows Server 2012 R2 上测试了这个 - 我有一个服务,它需要大约三分钟才能停止......当运行“net stop”时,命令不会' t 在 CMD 文件完成之前,服务可执行文件实际停止并从任务管理器中消失。它可以在更新的服务器上运行,而一些较旧的 cmets 说它不能。 net stop返回后,如果使用sc query "My Service Name" | find "STATE"查看状态,部分服务可能处于STOP_PENDING状态【参考方案2】:
sc stop webdriveservice
:loop
sc query webdriveservice | find "STOPPED"
if errorlevel 1 (
  timeout 1
  goto loop
)

【讨论】:

优秀的答案。只是一个问题:为什么是 TIMEOUT 而不是 SLEEP? TIMEOUT 会被按键绕过,我认为这在批处理文件中并不是一个理想的效果(在专注于 cmd 窗口时很容易误按一个键)。 实际上,它是 2003 Resource Kit 的一部分。我以为它是在标准的 Windows 安装中,我的错。 timeout 5 /nobreak 将仅在 CTRL+C 时退出【参考方案3】:

如上所述,NET STOP 会向服务发送停止命令,但是,如果服务花费的时间超过一定时间(我的观察是 20 秒左右),NET STOP 不会等待服务实际停止在返回之前。

要真正暂停批处理文件直到服务停止,您需要使用类似于这些线程中概述的方法:

How to check if a service is running via batch file and start it, if it is not running?

Stopping/Starting a remote Windows service and waiting for it to open/close

【讨论】:

不是反对者(虽然我可以猜到是谁),但这个答案包含错误信息。 NET STOP 等待服务停止,直到某个点。我从来没有让服务尝试停止整整四分钟,所以我不能说NET STOP 等待了多长时间,但它确实等待了相当长的一段时间,而不是@987654326 @.\ @LittleBobbyTables 该帖子已更新以说明您观察到的情况。如果您查看 microsoft 团队编写的内容(下面的链接),您会发现 SCM 一次只与一项服务对话,因此它不会永远等待任何一项服务。 NET SEND 只是向 SCM 发送 cmd 的一种方式,与服务管理器中的相同。 blogs.msdn.com/b/bclteam/archive/2009/02/19/… 从@Jonesome 链接的博客中提取更多信息:控制超时的注册表项是HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout。默认值显然是 20 秒,但在我的 Windows 8.1 Enterprise 机器上是 5 秒(可能会被组策略更改)。 @Stajs on Windows 2012 我将我的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout 设置为 DWORD 120000 并且它完全没有效果 - 即使服务正在关闭但没有停止,网络停止仍然在 10-15 秒后返回,不会再停 45 秒【参考方案4】:

我认为net stop [Service] 应该等到服务完全停止后再继续。 sc stop [Service] 只是向服务发送“停止”消息。

【讨论】:

@Jonesome - 与其投反对票,不如提供一个更好的答案? 公平通话!完毕!投反对票的原因是两个答案都包含错误的信息(我在 win7 和 win2008 上进行了测试,并且根据经验知道 XP 和其他版本的行为相同)。【参考方案5】:

net stop 也有类似的问题。它在服务确实停止时返回,但可执行文件可能仍在运行。 由于升级原因,这还不够好,我们需要等到过程完成。

我使用了一个简单的循环来等待服务可执行文件实际完成:

net stop "ServiceName"
:loop1
set _CmdResult=""
for /f "tokens=1" %%a in ('TASKLIST ^| FINDSTR ServiceName.exe') do set _CmdResult=%%a
if not %_CmdResult% == ""  (
  timeout 5
  goto loop1
)

一旦可执行文件完成,循环就会中断。

【讨论】:

【参考方案6】:

这有点粗略,但它对我有用,以确保我可以安排每日批处理文件来实质上重新启动服务。

NET STOP [服务]

:再试一次

超时 /T 10 /NOBREAK

NET START [服务]

IF %ERRORLEVEL% NEQ 0 GOTO TryAgain

我通过这段代码 sn-p 意识到,如果服务无法成功启动,这可能会导致无限循环。我只是想基本上展示如何使用 TIMEOUT 来解决这个问题,其中服务可能需要比 NET STOP 命令允许的时间更长的时间才能停止。

【讨论】:

【参考方案7】:

在命令之间使用&& 符号。 && 符号等待完成前一个命令,然后再继续执行下一个命令。

所有命令必须位于同一命令行。您可以连续使用任意数量的命令。

您也可以使用pause 命令。这样,在进行下一个过程之前,要求按任意键。

例如:

sc qdescription "MyServiceName" && echo. && sc stop "MyServiceName" && echo. && echo          [ "MyServiceName" service stopped ] && echo. && pause

【讨论】:

以上是关于在服务停止完成之前暂停批处理文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确暂停/停止线程?

如何用批处理文件(.bat)停止或启动windows的服务 ?

线程的停止与暂停

如何暂停、停止和重置 AUFilePlayer?

exit-code影响配置文件吗

Windows 服务的批处理文件停止、归档日志并重新启动服务