114

I want to write a batch file that performs the following operations:

  • Check if a service is running
    • If is it running, quit the batch
    • If it is not running, start the service

The code samples I googled so far turned out not to be working, so I decided not to post them.

Starting a service is done by:

net start "SERVICENAME"
  1. How can I check if a service is running, and how to make an if statement in a batchfile?
  2. I'm a bit confused. What is the argument I have to pass onto the net start? The service name or its display name?
citronas
  • 19,035
  • 27
  • 96
  • 164
  • 3
    Dirty programming: when the only thing you want to do is to start the service if it is not running, just issue the start command. If it is not running it will start the service. If it is running than you get an error message but the service is running (and does not stop). Dirty but it works. However, when you want to execute other comments only if you had to start the service, then definitly go with the cleaner version from lc. – Peter Schuetze Mar 08 '12 at 18:05
  • @Peter Schuetze: Yeah, your objection is correct if starting the service is the only purpose. I also included logging starts et cetera, so I sticked with the solution of lc. – citronas Mar 09 '12 at 13:18

14 Answers14

195

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.

hxysayhi
  • 1,888
  • 18
  • 25
lc.
  • 113,939
  • 20
  • 158
  • 187
  • Awesome. Thanks for your effort. Unfortunately it does not work? Maybe I'm too stupid for this. I replaced "MyServiceName" with "SCardSvr" (escaped) as a test, put everything into a batchfile, executed it, but the service does not start up. Even if I replace net start with something else, like printing into a file, it will not be executed. Would you mind taking a second look please? =) – citronas Jul 24 '10 at 13:07
  • Oops I had some extra stuff in the first line there...Try this. And if it doesn't work, what happens when you run `sc query "SCardSvr"` from a command line? – lc. Jul 24 '10 at 13:21
  • 1
    Do you have "SCardSvr" in quotes? I don't believe it should be, – LittleBobbyTables - Au Revoir Jul 24 '10 at 13:22
  • @LittleBobbyTables: You are right. Without quotes made it work. I'm so stupid :-| Thanks for your help – citronas Jul 24 '10 at 13:37
  • @Mark Good to note. I guess you'll have to replace that string with whatever it needs to be for the target OS language. I assume "RUNNING" as well. – lc. Sep 27 '19 at 06:10
  • You do realize you can simplify the first line and get the same result? With: `for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName"^|find /i "STATE"') do (` – Leptonator Sep 22 '20 at 16:42
  • 1
    Small remark for anyone dropping by. Under Powershell you need to add ".exe": `sc.exe query "MyServiceName"`. Since `sc` is an alias for `Set-Content` (You can check with `Get-Alias "sc"`). – Henk Poley May 12 '21 at 07:03
36

To toggle a service use the following;

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

Paul C
  • 4,687
  • 5
  • 39
  • 55
  • 1
    It works because of the exit code from start. If the start command fails it's probably because it's already running (and either way subsequently stopping it won't hurt), so you try stopping it. – lc. Mar 27 '12 at 15:34
  • 3
    the command is structured such that if net start fails, it then stops it (due to the || which means else), but if net start runs, then the net stop doesnt execute. brilliant! – Doctor DOS May 18 '12 at 15:35
  • 1
    This is the best answer in my opinion, and maybe @citronas should consider marking it as the accepted answer: simple, smart and elegant, and fits to a site like StackOverflow. Make it simple! – Sopalajo de Arrierez Aug 01 '15 at 12:36
  • 2
    Not to be nitpicky (OK, maybe just a little), but the `||` is actually an `OR` operator, although in this case it's **functionally** an `ELSE` statement. This is a subtle, but important difference. Still got my +1 -- I do this all the time in Unix/Linux shell scripting, don't know why I never thought of doing this in Windows batch. – Deacon Dec 04 '15 at 13:04
  • This seems dangerously oversimplified. I'd never want to use it for something I was automating for batch processing or giving to someone else to use... but it's just what the doctor ordered for a quick icon I can put on my own desktop for a service I need to quickly toggle now and then. – Joel Coehoorn Feb 07 '17 at 15:18
23

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.

LittleBobbyTables - Au Revoir
  • 32,008
  • 25
  • 109
  • 114
  • 3
    Thanks for your help, while trying to integrate what you posted, I much increas my batch skills ;) – citronas Jul 24 '10 at 13:39
16

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
)
NYCdotNet
  • 4,500
  • 1
  • 25
  • 27
Dr.eel
  • 1,837
  • 3
  • 18
  • 28
  • Yep! "Space" always hits suddenly in your back! – Dr.eel Jan 08 '16 at 16:07
  • 2
    Almost perfect answer. I'd just fix to this line: Net start "%ServiceName%">nul||( – Cesar Jan 24 '17 at 23:16
  • I've made the script universal so It allows me to use in Windows Scheduler tasks. Just replace `Set ServiceName=Jenkins` with `Set ServiceName=%~1` and call it like `watch-service.bat "Jenkins"` – Dr.eel Jan 31 '17 at 07:30
  • @Ant_222 It uses 'queryex' instead of 'query' which is language dependent. And why you think it's not Windows batch? Have you tried to use it? – Dr.eel Aug 17 '17 at 19:25
  • What does it mean /v in your script? Perhaps you have link to all those scripting commands? – FrenkyB Dec 08 '20 at 03:38
  • 1
    /v is to show not matching strings. Find a string with STATE, and not containing RUNNING – Dr.eel Apr 15 '21 at 09:55
  • Sorry but this is _not_ "language independent": as stated in my answer (and visible in referenced one) some locales have translated the **status descriptions**, thereby breaking English-based string comparisons. My take: use the numeric identifier, as translators will (hopefully) leave it untouched... – Helder Magalhães Nov 04 '22 at 18:01
16

That should do it:

FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING"
IF ERRORLEVEL 1 SC start %%a)
Kristina
  • 15,859
  • 29
  • 111
  • 181
5

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.

sagelightning
  • 51
  • 1
  • 1
  • 2
    That is a useful answer, however it is important to note, that is will only work if the service has stopped with exit(-1). If the service exited gracefully (even with error message) Auto Recover will not trigger. It also won't trigger if the service was killed manually by user. – Art Gertner Jan 06 '16 at 09:22
  • @sagelightning: We need admin access to try this way. – Kumar M Jan 11 '19 at 23:02
  • @ArtGertner - Killing (via task manager) a service process will be interpreted as "crash" and will trigger a recovery. – Martin Ba Feb 22 '19 at 10:02
4

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.)

Sicco
  • 6,167
  • 5
  • 45
  • 61
  • 11
    It will be better for every one if you write your answer in english. – j0k Sep 03 '12 at 12:34
  • 2
    Not sure why the downvote. This is an important point and a reason to avoid string comparisons if possible. In this case you have to change the string depending on the default language of the target Windows installation. – lc. Sep 13 '12 at 07:50
  • 2
    @lc: Would it be reasonable to include an answer for each language? It might be more useful to reference (or include) a resource which says what string to search for a given language. – Mike Bailey Jun 28 '13 at 18:25
4

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
)
Sunil Lama
  • 4,531
  • 1
  • 18
  • 46
Magige Daniel
  • 1,024
  • 1
  • 10
  • 10
2
@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"
Logan78
  • 31
  • 2
1

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.
      )
    )

  )
)
Community
  • 1
  • 1
BYoung
  • 123
  • 1
  • 9
1

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
}
}
KR Akhil
  • 877
  • 3
  • 15
  • 32
1

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
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
Aylian Craspa
  • 422
  • 5
  • 11
0

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"
Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • returns "%%a was unexpected at this time." – ETL Aug 24 '23 at 18:00
  • 1
    You are running it from the `cmd` console then @ETL, this runs in Batch-file. If you wnat to run in cmd, then remove one percentage from `%%a` it should then be `%a` and `%b` everywhere in the line. I.e `@for /f "tokens=1,* delims=: " %a in ('sc queryex state=Inactive') do net start "%b"` – Gerhard Aug 25 '23 at 07:24
  • Thanks. But I'm confused, where in this script do I put the actual name of the service I'm querying? – ETL Aug 25 '23 at 11:59
  • `sc queryex yourservicename` @ETL – Gerhard Aug 25 '23 at 18:13