How to Start a Stopped Windows Service Automatically Using a Script
If you have worked with SharePoint Server 2010, you may have noticed that once in a while, especially after a reboot, the Forefront Identity Manager (FIMService) doesn’t start. Sometimes both the FIMService and the Forefront Identity Manager Synchronization Service (FIMSynchronizationService) don’t start. Without FIM services for all practical purposes your SharePoint is out of commission.
To address this issue, I figured it would be great to write a batch file that will look for these services to see if they are running, if not, it will start these services and log the activity in a log file. If the service is running on multiple computers. this script will even take care of all the remote servers and start the service, assuming you have the proper administrative rights. I want to thank Jerry, a Microsoft MVP – Windows Expert – Consumer, for writing this script on forums.techguy.org. I modified his original script to fit my need.
NOTE: To benefit from the script in this article you must have at least a fundamental knowledge of batch files and scripting. You should also understand what environmental variables are and how to modify the system path.
What Does the Script Do?
I wrote this batch file that will check to see if the two FIM services have started. If not, it will start them automatically. Here’s exactly what the script does. It sets a log file, called log.txt. If the file exists, it will delete it so you only have the information from the last time you ran the script. Instead of using the “net start” command, which will work on the local computer, it uses psservice.exe which is part of Sysinternals Suite and can be downloaded from Microsoft’s Web site here. I wrote the batch file with SharePoint in mind but you can use this script for any service on any Windows computer. In a typical SharePoint environment, SharePoint is installed on more than one server. If you want to make sure that the service is running on multiple computers, simply add the names of the computers in the computers.txt file.
Best Practice: Add the folder where you have copied the Sysinternals tools, such as psservice.exe, to the system’s path. That way you can run the psservice.exe from any folder.
I like to keep the batch file (FIM.bat), the log file (log.txt) and the server name file (computers.txt) in a folder called BATCH. I also like to add the BATCH folder to the path.
You should save the script as a .bat file. Make sure that it does not have a .txt extension. If you want, you can schedule this batch file to run every so often. That way you can ensure that your services are always running. If a service has already started it will only take a second for it to check and log the information. There is no overhead that you need to worry about. You can check out my blog post on how to accomplish that. The link is posted at the end of this article.
Determine the Name of the Service
In the script you should replace the name of the service with your service name. To find out what service name you should use go to Services Console (services.msc) and double-click the service. On the General name look for Service name. For example, the name of the Forefront Identity Manager Service is FIMService, as shown below.
The script will check to see if the service is running, stopped, or paused and will document the result accordingly in the log file. I have set the script to check the status 10 times. You can adjust this setting if necessary.
Running Same Script for Multiple Services
To make things simple, I start both the services in the same script. There are other ways to handle this situation but I wanted my script to be pretty flexible and decided to implement what I wanted to accomplish using this method.
In the first section, I check for the FIMService and in the second section I essentially run the same script for FIMSynchronizationService with slight modification. For example, I don’t want the log file to be deleted after the FIMService is started because I also want to see the results for the second service so I commented out the line that deletes the log file in FIMSynchronizationService section.
Dealing With Multiple Computers
You can use this script to remotely start a service on remote computers. Simply add the name of the computers in the computers.txt file on separate files. If you have only one computer, just add its name to the computers.txt file. For example, if you have 3 servers named server1, server2, and server3, your computers.txt file will look like this.
Once the batch file is complete you can verify the status of the services in the Services Console and also check the log file for the activity that took place.
The Log File
The script also utilizes a log.txt file. Each time the batch file is executed it first deletes the old log file and then creates a new log.txt file and enters the necessary information in the file for you. If both the FIM services were stopped, your log file will display the following information.
Sample Script
I named my script FIM.bat because I am using it to start two FIM services. Obviously, you can name it whatever you want but keep the name short.
Best Practice: Use the 8.3 file naming convention for your batch file. In other words, do not use more than 8 characters (excluding the extension) for the file name. For example, instead of naming it something like startsrvcs.bat, name it strtsrvc.bat to follow the 8.3 file naming convention.
You can copy the following text to the clipboard and then paste it into notepad. Modify the script as mentioned above and then save it as a batch file using 8.3 naming convention. Make sure you test the script in a test environment first to make sure it does what you expect it to do.
@echo off
cls
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Check the status for FIMService
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Set LogFile=log.txt
If Exist %LogFile% Del %LogFile%
Set Errors=
For /f “tokens=1” %%i In (computers.txt) Do (
Call :process %%i
If %ErrFlag%==1 Set Errors=1
)
If Defined Errors Echo FIMService on some machines could not be started. Please check the log in %LogFile%.
Goto :STOP
Set LogFile=log.txt
If Exist %LogFile% Del %LogFile%
Set Errors=
For /f “tokens=1” %%i In (computers.txt) Do (
Call :process %%i
If %ErrFlag%==1 Set Errors=1
)
If Defined Errors Echo FIMService on some machines could not be started. Please check the log in %LogFile%.
Goto :STOP
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Subroutines
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:process
:: %1 is the Remote Machine Name
Set ErrFlag=0
Set SERVICE1=FIMService
:FIMService
Call :CheckState %1
If “%STATE%”==”RUNNING” (
Echo FIMService on %1 has already started.>> %LogFile%
Goto :EOF
)
If “%STATE%”==”STOPPED” (
Echo FIMService on %1 is in Stop mode. Attempting to start the service….>> %LogFile%
psservice \\%1 Start %SERVICE1% 2>Nul
Call :Wait %1
Goto :EOF
)
If “%STATE%”==”PAUSED” (
Echo FIMService on %1 is in Paused mode. Attempting to start the service…>> %LogFile%
psservice \\%1 cont %SERVICE1% 2>Nul
Call :Wait %1 Re-
Goto :EOF
)
Echo FIMService on %1 is in an Unknown state. Please check the %1 system.>> %LogFile%
Set Errflag=1
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:CheckState
Set STATE=
For /F “Tokens=3 Delims=: ” %%a In (‘psservice 2^>Nul \\%1 query %SERVICE1%^|Find /I “STATE”‘) Do Set STATE=%%a
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Wait
:: %1 is the Remote Machine Name
:: %2 is null if attempting to start, is Re- if restarting
Set loop=0
:Check
:: Will check state 10 times, adjust as needed.
If %loop%==10 Goto NoStart
:: Wait 1 second for service to (Re-)start (can also use sleep utility)
:: adjust -w as needed units are milliseconds
Ping 1.0.0.0 -n 1 -w 1000 >Nul
Call :CheckState %1
If NOT “%STATE%”==”RUNNING” (set /a loop+=1) & Goto Check
Echo FIMService on %1 has %2started successfully.>> %LogFile%
GOTO :EOF
:NoStart
Echo Unable to %2start FIMService on %1>> %LogFile%
Set ErrFlag=1
Goto :EOF
)
:STOP
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Check the status for FIMSynchronizationService
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
Set LogFile=log.txt
:: If Exist %LogFile% Del %LogFile% (Log file should not be deleted after the FIMService is started)
Set Errors=
For /f “tokens=1” %%i In (computers.txt) Do (
Call :process %%i
If %ErrFlag%==1 Set Errors=1
)
If Defined Errors Echo FIMSynchronizationService on some machines could not be started. Please check the log in %LogFile%.
Goto :STOP
Set LogFile=log.txt
If Exist %LogFile% Del %LogFile%
Set Errors=
For /f “tokens=1” %%i In (computers.txt) Do (
Call :process %%i
If %ErrFlag%==1 Set Errors=1
)
If Defined Errors Echo FIMSynchronizationService on some machines could not be started. Please check the log in %LogFile%.
Goto :STOP
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Subroutines
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:process
:: %1 is the Remote Machine Name
Set ErrFlag=0
Set SERVICE1=FIMSynchronizationService
:FIMSynchronizationService
Call :CheckState %1
If “%STATE%”==”RUNNING” (
Echo FIMSynchronizationService on %1 has already started.>> %LogFile%
Goto :EOF
)
If “%STATE%”==”STOPPED” (
Echo FIMSynchronizationService on %1 is in Stop mode. Attempting to start the service….>> %LogFile%
psservice \\%1 Start %SERVICE1% 2>Nul
Call :Wait %1
Goto :EOF
)
If “%STATE%”==”PAUSED” (
Echo FIMSynchronizationService on %1 is in Paused mode. Attempting to start the service…>> %LogFile%
psservice \\%1 cont %SERVICE1% 2>Nul
Call :Wait %1 Re-
Goto :EOF
)
Echo FIMSynchronizationService on %1 is in an Unknown state. Please check the %1 system.>> %LogFile%
Set Errflag=1
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:CheckState
Set STATE=
For /F “Tokens=3 Delims=: ” %%a In (‘psservice 2^>Nul \\%1 query %SERVICE1%^|Find /I “STATE”‘) Do Set STATE=%%a
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Wait
:: %1 is the Remote Machine Name
:: %2 is null if attempting to start, is Re- if restarting
Set loop=0
:Check
:: Will check state 10 times, adjust as needed.
If %loop%==10 Goto NoStart
:: Wait 1 second for service to (Re-)start (can also use sleep utility)
:: adjust -w as needed units are milliseconds
Ping 1.0.0.0 -n 1 -w 1000 >Nul
Call :CheckState %1
If NOT “%STATE%”==”RUNNING” (set /a loop+=1) & Goto Check
Echo FIMSynchronizationService on %1 has %2started successfully.>> %LogFile%
GOTO :EOF
:NoStart
Echo Unable to %2start FIMSynchronizationService on %1>> %LogFile%
Set ErrFlag=1
Goto :EOF
)
:STOP
By the way, I have tested this batch file numerous times and it worked perfectly every single time. If you decide to schedule this batch file, check out my article How to run a batch file as a task in Windows Server 2008.
Copyright ©2011 Zubair Alexander. All rights reserved.