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

我想编写一个执行以下操作的批处理文件:

  • 检查服务是否正在运行
    • 如果正在运行,请退出批处理
    • 如果它没有运行,请启动服务

到目前为止,我在谷歌上搜索的代码示例并没有起作用,所以我决定不发布它们。

启动服务的方法是:

net start "SERVICENAME"
  1. 如何检查服务是否正在运行,以及如何在批处理文件中创建 if 语句?
  2. 我有点糊涂了。我要传递到网开始的论点是什么?服务名称还是显示名称?
378202 次浏览

That should do it:

FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING"
IF ERRORLEVEL 1 SC start %%a)

You can use the following command to see if a service is running or not:

sc query [ServiceName] | findstr /i "STATE"

When I run it for my NOD32 Antivirus, I get:

STATE                       : 4 RUNNING

If it was stopped, I would get:

STATE                       : 1 STOPPED

You can use this in a variable to then determine whether you use NET START or not.

The service name should be the service name, not the display name.

To check a service's state, use sc query <SERVICE_NAME>. For if blocks in batch files, check the documentation.

The following code will check the status of the service MyServiceName and start it if it is not running (the if block will be executed if the service is not running):

for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName" ^| findstr "        STATE"') do (
if /I "%%H" NEQ "RUNNING" (
REM Put your code you want to execute here
REM For example, the following line
net start "MyServiceName"
)
)

Explanation of what it does:

  1. Queries the properties of the service.
  2. Looks for the line containing the text "STATE"
  3. Tokenizes that line, and pulls out the 3rd token, which is the one containing the state of the service.
  4. Tests the resulting state against the string "RUNNING"

As for your second question, the argument you will want to pass to net start is the service name, not the display name.

To toggle a service use the following;

NET START "Distributed Transaction Coordinator" ||NET STOP "Distributed Transaction Coordinator"

Cuando se use Windows en Español, el código debe quedar asi (when using Windows in Spanish, code is):

for /F "tokens=3 delims=: " %%H in ('sc query MYSERVICE ^| findstr "        ESTADO"') do (
if /I "%%H" NEQ "RUNNING" (
REM Put your code you want to execute here
REM For example, the following line
net start MYSERVICE
)
)

Reemplazar MYSERVICE con el nombre del servicio que se desea procesar. Puedes ver el nombre del servicio viendo las propiedades del servicio. (Replace MYSERVICE with the name of the service to be processed. You can see the name of the service on service properties.)

@echo off


color 1F




@sc query >%COMPUTERNAME%_START.TXT




find /I "AcPrfMgrSvc" %COMPUTERNAME%_START.TXT >nul


IF ERRORLEVEL 0 EXIT


IF ERRORLEVEL 1 NET START "AcPrfMgrSvc"

I also wanted an email sent if the service was started this way so added a bit to @Ic code just thought I would post it in case it helped anyone. I used SendMail but there are other command line options How to send a simple email from a Windows batch file?

set service=MyServiceName


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


net start %service%


for /F "tokens=3 delims=: " %%H in ('sc query %service% ^| findstr "        STATE"') do (
if /I "%%H" EQ "RUNNING" (
SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% succeded.
) else (
SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% failed.
)
)


)
)

I just found this thread and wanted to add to the discussion if the person doesn't want to use a batch file to restart services. In Windows there is an option if you go to Services, service properties, then recovery. Here you can set parameters for the service. Like to restart the service if the service stops. Also, you can even have a second fail attempt do something different as in restart the computer.

Language independent version.

@Echo Off
Set ServiceName=Jenkins




SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
echo %ServiceName% not running
echo Start %ServiceName%


Net start "%ServiceName%">nul||(
Echo "%ServiceName%" wont start
exit /b 1
)
echo "%ServiceName%" started
exit /b 0
)||(
echo "%ServiceName%" working
exit /b 0
)
@Echo off


Set ServiceName=wampapache64


SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(


echo %ServiceName% not running
echo


Net start "%ServiceName%"




SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
Echo "%ServiceName%" wont start
)
echo "%ServiceName%" started


)||(
echo "%ServiceName%" was working and stopping
echo


Net stop "%ServiceName%"


)




pause

Starting Service using Powershell script. You can link this to task scheduler and trigger it at intervals or as needed. Create this as a PS1 file i.e. file with extension PS1 and then let this file be triggered from task scheduler.

To start stop service

in task scheduler if you are using it on server use this in arguments

-noprofile -executionpolicy bypass -file "C:\Service Restart Scripts\StopService.PS1"

verify by running the same on cmd if it works it should work on task scheduler also

$Password = "Enter_Your_Password"
$UserAccount = "Enter_Your_AccountInfor"
$MachineName = "Enter_Your_Machine_Name"
$ServiceList = @("test.SocketService","test.WcfServices","testDesktopService","testService")
$PasswordSecure = $Password | ConvertTo-SecureString -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $UserAccount, $PasswordSecure


$LogStartTime = Get-Date -Format "MM-dd-yyyy hh:mm:ss tt"
$FileDateTimeStamp = Get-Date -Format "MM-dd-yyyy_hh"
$LogFileName = "C:\Users\krakhil\Desktop\Powershell\Logs\StartService_$FileDateTimeStamp.txt"




#code to start the service


"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STARTING SERVICE  ##########################" >> $LogFileName


for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName


Write-Output "`n####################################"
Write-Output "Starting Service - " $ServiceList[$i]


"$LogStartTime => Starting Service: $ServiceName" >> $LogFileName
Start-Service $ServiceList[$i]


$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}


if($ServiceState.Status -eq "Running")
{
"$LogStartTime => Started Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Started Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`n Service didn't Start. Current State is - "
Write-Host $ServiceState.Status
}
}


#code to stop the service


"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STOPPING SERVICE  ##########################" >> $LogFileName


for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName


Write-Output "`n####################################"
Write-Output "Stopping Service - " $ServiceList[$i]


"$LogStartTime => Stopping Service: $ServiceName" >> $LogFileName
Stop-Service $ServiceList[$i]


$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}


if($ServiceState.Status -eq "Stopped")
{
"$LogStartTime => Stopped Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Stopped Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`nService didn't Stop. Current State is - "
Write-Host $ServiceState.Status
}
}

Related with the answer by @DanielSerrano, I've been recently bit by localization of the sc.exe command, namely in Spanish. My proposal is to pin-point the line and token which holds numerical service state and interpret it, which should be much more robust:

@echo off


rem TODO: change to the desired service name
set TARGET_SERVICE=w32time


set SERVICE_STATE=
rem Surgically target third line, as some locales (such as Spanish) translated the utility's output
for /F "skip=3 tokens=3" %%i in ('""%windir%\system32\sc.exe" query "%TARGET_SERVICE%" 2>nul"') do (
if not defined SERVICE_STATE set SERVICE_STATE=%%i
)
rem Process result
if not defined SERVICE_STATE (
echo ERROR: could not obtain service state!
) else (
rem NOTE: values correspond to "SERVICE_STATUS.dwCurrentState"
rem https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
if not %SERVICE_STATE%==4 (
echo WARNING: service is not running
rem TODO: perform desired operation
rem net start "%TARGET_SERVICE%"
) else (
echo INFORMATION: service is running
)
)

Tested with:

  • Windows XP (32-bit) English
  • Windows 10 (32-bit) Spanish
  • Windows 10 (64-bit) English

Maybe a much simpler way? Just adding to the list of answers here:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"

For Windows server 2012 below is what worked for me. Replace only "SERVICENAME" with actual service name:

@ECHO OFF
SET SvcName=SERVICENAME


SC QUERYEX "%SvcName%" | FIND "STATE" | FIND /v "RUNNING" > NUL && (
ECHO %SvcName% is not running
ECHO START %SvcName%


NET START "%SvcName%" > NUL || (
ECHO "%SvcName%" wont start
EXIT /B 1
)
ECHO "%SvcName%" is started
EXIT /B 0
) || (
ECHO "%SvcName%" is running
EXIT /B 0
)