检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动

Posted

技术标签:

【中文标题】检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动【英文标题】:check if a list of windows services are running and start if not from batch file检查 Windows 服务列表是否正在运行,如果不是从批处理文件启动 【发布时间】:2021-06-26 09:12:26 【问题描述】:

我正在寻找一个批处理脚本来检查是否有一些服务正在运行,如果没有启动它们,这就是我到目前为止检查特定服务是否正在运行的内容:

for /F "tokens=3 delims=: " %%H in ('sc query "service1" ^| findstr "        STATE"') do (
  if /I "%%H" NEQ "RUNNING" (
   net start "service1"
  )

但是,我想修改这个 for 循环以检查是否有其他服务的匹配项,例如“service2”、“service3”、“service4”和“service5”,但我不知道该怎么做.是否可以将这些匹配项包含在同一个 For 循环中?

谢谢

【问题讨论】:

不是检查字符串RUNNING那么简单。一个服务,如果启动了,可以有多个状态,仅仅因为状态不是RUNNING,并不代表它可以启动。状态可以是StoppedStart PendingStop PendingRunningContinue PendingPause PendingPausedUnknown。无论如何,我不确定如果您要求启动已在运行的服务会发生什么,但我假设可能只是一条错误消息,(您可以发送到NUL)。那么为什么不尝试启动所有这些,看看会发生什么。使用sc start,而不是net start 【参考方案1】:

这是一个你可能没有考虑过的替代方案,(忽略了我之前评论中的建议),它可以直接在 cmd 中运行,或者从 batch-file 中运行:

%SystemRoot%\System32\wbem\WMIC.exe Service Where "Name='Service1' Or Name='Service2' Or Name='Service3' Or Name='Service4 Or Name='Service5 And Started='TRUE' And State !='Running'" Call StartService >NUL 2>&1

您需要自己决定是否需要 Started='TRUE' 部分,但我建议您首先一定要保留它。

【讨论】:

我试试看是否需要相应地调整“开始”标志,谢谢【参考方案2】:

如果您想在一个循环中使用 FOR 批量执行此操作:

FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2"^) ^| FINDSTR /C:"SERVICE_NAME" /C:"        STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" CALL NET START %%LOCALV_SERV%%))

我们通过连接多个 SC 输出一次查询多个服务,然后在这里使用 FINDSTR 功能一次搜索多个字符串以获得服务名称和服务状态。

按照@Compo 的建议,您应该测试许多其他服务状态。

那么对于您的用例,命令应该是:

FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2" ^& SC QUERY "Service3" ^& SC QUERY "Service4" ^& SC QUERY "Service5"^) ^| FINDSTR /C:"SERVICE_NAME" /C:"        STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" CALL NET START %%LOCALV_SERV%%))

将 Service1、Service2、Service3、Service4、Service5 替换为您要定位的服务名称。

由于@Compo 指出使用 CALL 进行延迟扩展可能不合适,因此这里是显式启用延迟扩展的相同脚本:

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2"^) ^| FINDSTR /C:"SERVICE_NAME" /C:"        STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" NET START !LOCALV_SERV!))

这是我的答案的扩展,基于 cmets,它仅在循环内需要的地方启用延迟扩展。这个版本还去掉了对%PATH%%PATHEXT%的依赖,提高了可读性:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

Set "SC=%SystemRoot%\System32\sc.exe"
Set "FS=%SystemRoot%\System32\findstr.exe"

For /F "Tokens=2-3 Delims=: " %%G In ('
    (%SC% Query "Service1" ^&
     %SC% Query "Service2" ^&
     %SC% Query "Service3" ^&
     %SC% Query "Service4" ^&
     %SC% Query "Service5"^) 2^>NUL
     ^| %FS% /BIC:"SERVICE_NAME:" /C:"        STATE "
') DO (
    If Not "%%G" == "" If "%%H" == "" Set "LOCALV_SERV=%%G"
    If Not "%%H" == "" If /I Not "%%H" == "RUNNING" (
        SetLocal EnableDelayedExpansion
        %SC% Start !LOCALV_SERV!
        EndLocal
    )
)

【讨论】:

谢谢,请问 service1 和 service2 是什么,以便我可以确定是否需要在我的用例中添加 3,4 和 5?我可以安全地假设我可以将我的字符串匹配附加到 FINDSTR,有点像这样 'FINDSTR /C:"service1" /C:"service2" ? @user1283674 您不需要更改 FINDSTR,它会从 sc 输出中自行获取服务名称。如果您有 5 个服务要检查,只需将 SC QUERY "Service1" ^& SC QUERY "Service2" 更改为 SC QUERY "Service1" ^& SC QUERY "Service2" ^& SC QUERY "Service3" ^& SC QUERY "Service4" ^& SC QUERY "Service5" 明白了,感谢您的宝贵时间 我认为在另一个 cmd.exe 实例中运行多个 sc.exe 命令和一个 findstr.exe 没有任何好处,然后是一系列 if 命令和一个 net.exe 命令, 做一个WMIC.exe 命令可以做的事情。还有为什么要使用不同的可执行文件net.exe,当你已经使用sc.exe,并且已经可以start 一个服务。此外,net.exe 不是批处理文件,如果您查看Call 命令的帮助信息,(命令提示符窗口中的call /?,您应该注意在这种情况下,Call 不是必需的或不需要的。 是的 Zilog80,我希望你不介意,但我添加了一个额外的示例,仅在需要的地方延迟扩展,在循环中,你的答案。我也赞成它,因为虽然它的效率较低,但从技术上讲,它是对特定问题的直接回答

以上是关于检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动的主要内容,如果未能解决你的问题,请参考以下文章

如何检查是不是在 C# 中安装了 Windows 服务

如何通过批处理文件检查服务是不是正在运行并启动它,如果它没有运行?

如何使用 C++ 检查进程是不是正在运行

如何验证 Windows 服务是不是正在运行

C#:如何以编程方式检查 Web 服务是不是已启动并正在运行?

如何检查 Kafka Server 是不是正在运行?