从批处理脚本启动Windows服务,并根据结果

时间:2016-10-22 01:13:04

标签: windows batch-file service error-handling command-line-interface

我有一个.bat脚本,试图在最后启动Windows服务。

:start_wildfly
echo.
set /p wildfly_service_name="Enter Wildfly service name: "
echo INFO: Starting %wildfly_service_name%...
echo.
call net start "%wildfly_service_name%"

我希望能够解释net start尝试的结果,以便我可以让我的脚本在失败时采取适当的操作(例如,如果服务已经运行,请重新启动它。如果服务名称如果用户没有足够的权限,则重新提示该名称,退出)。

问题是NET命令没有返回记录的Win32_Service class codes

它确实在控制台上回显错误:

The requested service has already been started.

More help is available by typing NET HELPMSG 2182.

请参阅http://ss64.com/nt/net_service.html以获取错误列表。

不幸的是,errorlevel变量在这些错误情况下总是2,因此我无法依赖它。

我现在要做的是在FIND命令的输出上运行NET,搜索特定的错误代码并对其采取行动。

net start Wildfly 2>&1 | FIND "2182"
if %errorlevel% equ 0 goto service_already_running

因此,FIND的结果存储在errorlevel中,我可以通过检查FIND是否为0来检查errorlevel是否成功。这有效。

现在,当我想检查多个错误代码时出现问题。我不知道如何扩展上面的代码以检查" 2185"例如,在这种情况下转到不同的标签。

我现在正试图将NET命令的整个结果存储到变量中,然后对该变量运行FINDSTR

setlocal EnableDelayedExpansion
set "output_cnt=0"
for /F "delims=" %%f in ('dir /b') do (
    set /a output_cnt+=1
    set "output[!output_cnt!]=%%f"
)
for /L %%n in (1 1 !output_cnt!) DO echo !output[%%n]!

这应该存储并回显输出的每一行,但最后一行似乎没有做任何事情。

然后我还发现了一些应该在变量中搜索并返回是否找到该字符串的代码:

echo.%output%|findstr /C:"2182" >nul 2>&1 && echo Found || echo Not found.

虽然我没有运气。我只是希望能够解释NET START <SERVICE>的结果并根据结果跳转到某些标签。

3 个答案:

答案 0 :(得分:2)

我希望能够解释net start尝试

的结果
  

这样我可以让我的脚本在失败时采取适当的操作(例如,如果服务已经运行,请重新启动它。如果服务名称无效,请再次提示输入名称,如果用户没有有足够的特权,退出)。

正如您所做的那样启动服务:

net start "%wildfly_service_name%"

现在检查服务的状态。

有两种方法可以做到这一点。

  1. 再次使用net start查看服务是否正在运行:

    net start | find "%wildfly_service_name%" > nul
    if errorlevel 1 echo The service is not running
    
  2. 使用sc(服务控制)检查服务状态:

    SC query %wildfly_service_name% | find "STATE" | find "STOPPED"
    

    或者

    sc query %wildfly_service_name% | find "STATE" | find "RUNNING"
    

    如果文字

  3. ,则上述两条陈述将返回%errorlevel% = 1

    进一步阅读

答案 1 :(得分:0)

以DavidPostill回答使用net start来检查服务状态,这是我的新解决方案:

echo.
echo INFO: Starting %wildfly_service_name%...
echo.

:verify_not_running
net start | find "%wildfly_service_name%" > nul
if %errorlevel% equ 0 goto restart_wildfly

:start_wildfly
net start "%wildfly_service_name%"
goto verify_running

:restart_wildfly
echo The %wildfly_service_name% service is already running. Will now restart...
net stop "%wildfly_service_name%"
net start "%wildfly_service_name%"

:verify_running
net start | find "%wildfly_service_name%" > nul
if errorlevel 1 goto start_wildfly

此脚本将首先验证服务未运行。

如果该服务已在运行,它将重新启动该服务。

在任何一种情况下,我都会在最后检查以确保服务现在已经启动。如果没有,请重复此过程。

请注意,我不再需要检查服务名称是否有效。现在,服务名称在脚本的早期硬编码,因此假定它是正确的。

为了处理权限不足的情况,我在脚本的开头添加了这个片段:

:check_permissions
net session >nul 2>&1
if errorlevel 1 (
    echo.
    echo ERROR: This script must be run as an Administrator. Please re-run the script from an elevated command prompt. 
    echo.
    echo Right-click "cmd.exe" from the Start menu and select "Run As Administrator".
    exit /b %error_level%
)

答案 2 :(得分:0)

您是对的;对于任何类型的错误,net命令显然总是返回2。但是,您可以使用sc start命令替代net start,并且确实会通过不同的退出状态指示不同的错误,尤其是对于实例来说,1056的服务已经在运行。因此,您可以使用use

sc start "%wildfly_service_name%"

然后再检查%errorlevel%