Home > PowerShell, SharePoint, SharePoint 2010 > SharePoint 2010: PowerShell to Clear the Timer Job Cache

SharePoint 2010: PowerShell to Clear the Timer Job Cache


I have been clearing the Timer Job Cache manually when needed for years. A few months back I looked for a script to do this automatically and ended up writing one since it can be a slow and laborious task to perform on a multi-server SharePoint farm, and I have now finally got around to sharing it here.

The Timer Job Cache may need to be cleared for a number of reasons, however the main ones I have come across are mainly in development environments when redeploying the same or updated solutions repeatedly, where updated assemblies are not used by timer jobs, and also if for example a small development VM runs out of disk space (frugal disk allocation) because of database transaction logs or data files filling up then the timer jobs stop working. I am sure there are several other reasons you might want or need to clear the Timer Job Cache.

The steps include the following, and perform each step on every server in the farm which has the timer service installed before moving onto the next step:

  • Stop the “SharePoint 2010 Timer” service.
  • Delete all the XML files in the config cache. There are loads of XML files that can be found in the folder “C:\ProgramData\Microsoft\SharePoint\Config\\”. Note there seems to only ever be one folder under Config which has a GUID. There are other folders which map onto this folder, but this one seems to be on every environment whereas the other locations may be found in different places on some environments. Therefore deleting the files from this folder should work in all environments.
  • Edit the “cache.ini” file in the same folder that contained the XML files, setting the content to “1” (without the double-quotes). This indicates that all cache settings need to be refreshed. Eventually this value gets automatically updated to another number when the cache is repopulated.
  • Start the “SharePoint 2010 Timer” service.

As indicated, this has to be performed on several servers, and can be quite time-consuming and laborious when performed manually. I usually take these steps while still developing a system every time after uninstalling solutions which contain timer jobs in our development environments before installing updated solutions, particularly where the assembly containing timer job code is updated, otherwise the timer job may continue running code from the older assembly which had been uninstalled but would otherwise still remain cached.

I looked around for a script to execute that performs all of these steps, and found a few which came close. The best I found was in Mickey Jervin’s SharePoint blog. However there were some limitations that I felt I could improve on. For example, it waited a predefined period after stopping or starting services before proceeding with further steps. I decided to automate this by making the script monitor the service status and wait only until the status was Stopped or Running as required before proceeding. I also found that I had to use sc.exe to stop and start the services on remote servers rather than WMI because of permissions related issues, whereas sc.exe just worked fine. I also found that only the Timer Service needed to be stopped, at least for my needs, and it should only try to stop the timer service on the servers in the farm which have the timer service installed (updated June 14th, 20:00).

Here is the final PowerShell script which can be run on any SharePoint server. It also outputs progress to the console regularly. It needs to be executed by a farm admin:

# Clear the SharePoint Timer Cache
#
# 2009 Mickey Kamp Parbst Jervin (mickeyjervin.wordpress.com)
# 2011 Adapted by Nick Hobbs (nickhobbs.wordpress.com) to work with SharePoint 2010,
# display more progress information, restart all timer services in the farm,
# and make reusable functions.

# Output program information
Write-Host -foregroundcolor White ""
Write-Host -foregroundcolor White "Clear SharePoint Timer Cache"

#**************************************************************************************
# References
#**************************************************************************************
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint")
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint.Administration")
[void][reflection.assembly]::LoadWithPartialName("System")
[void][reflection.assembly]::LoadWithPartialName("System.Collections")
#**************************************************************************************

#**************************************************************************************
# Constants
#**************************************************************************************
Set-Variable timerServiceName -option Constant -value "SharePoint 2010 Timer"
Set-Variable timerServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Timer"

#**************************************************************************************
# Functions
#**************************************************************************************

#<summary>
# Stops the SharePoint Timer Service on each server in the SharePoint Farm.
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function StopSharePointTimerServicesInFarm([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
Write-Host ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm.Servers)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then stop the service
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Stop '$timerServiceName' service on server: "
Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$timerServiceName'"
$serviceInternalName = $service.Name
sc.exe \\$serverName stop $serviceInternalName > $null

# Wait until this service has actually stopped
WaitForServiceState $serverName $timerServiceName "Stopped"

break;
}
}
}

Write-Host ""
}

#<summary>
# Waits for the service on the server to reach the required service state.
# This can be used to wait for the "SharePoint 2010 Timer" service to stop or to start
#</summary>
#<param name="$serverName">The name of the server with the service to monitor.</param>
#<param name="$serviceName">The name of the service to monitor.</param>
#<param name="$serviceState">The service state to wait for, e.g. Stopped, or Running.</param>
function WaitForServiceState([string]$serverName, [string]$serviceName, [string]$serviceState)
{
Write-Host -foregroundcolor DarkGray -NoNewLine "Waiting for service '$serviceName' to change state to $serviceState on server $serverName"

do
{
Start-Sleep 1
Write-Host -foregroundcolor DarkGray -NoNewLine "."
$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$serviceName'"
}
while ($service.State -ne $serviceState)

Write-Host -foregroundcolor DarkGray -NoNewLine " Service is "
Write-Host -foregroundcolor Gray $serviceState
}

#<summary>
# Starts the SharePoint Timer Service on each server in the SharePoint Farm.
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function StartSharePointTimerServicesInFarm([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
Write-Host ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm.Servers)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then start the service
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Start '$timerServiceName' service on server: "
Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "DisplayName='$timerServiceName'"
[string]$serviceInternalName = $service.Name
sc.exe \\$serverName start $serviceInternalName > $null

WaitForServiceState $serverName $timerServiceName "Running"

break;
}
}
}

Write-Host ""
}

#<summary>
# Removes all xml files recursive on an UNC path
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function DeleteXmlFilesFromConfigCache([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
Write-Host ""
Write-Host -foregroundcolor DarkGray "Delete xml files"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm.Servers)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service delete the XML files from the config cache
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Deleting xml files from config cache on server: "
Write-Host -foregroundcolor Gray $serverName

# Remove all xml files recursive on an UNC path
$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\*.xml"
Remove-Item -path $path -Force

break
}
}
}

Write-Host ""
}

#<summary>
# Clears the SharePoint cache on an UNC path
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function ClearTimerCache([Microsoft.SharePoint.Administration.SPFarm]$farm)
{
Write-Host ""
Write-Host -foregroundcolor DarkGray "Clear the cache"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm.Servers)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then force the cache settings to be refreshed
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Clearing timer cache on server: "
Write-Host -foregroundcolor Gray $serverName

# Clear the cache on an UNC path
# 1 = refresh all cache settings
$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\cache.ini"
Set-Content -path $path -Value "1"

break
}
}
}

Write-Host ""
}

#**************************************************************************************
# Main script block
#**************************************************************************************

# Get the local farm instance
[Microsoft.SharePoint.Administration.SPFarm]$farm = [Microsoft.SharePoint.Administration.SPFarm]::get_Local()

# Stop the SharePoint Timer Service on each server in the farm
StopSharePointTimerServicesInFarm $farm

# Delete all xml files from cache config folder on each server in the farm
DeleteXmlFilesFromConfigCache $farm

# Clear the timer cache on each server in the farm
ClearTimerCache $farm

# Start the SharePoint Timer Service on each server in the farm
StartSharePointTimerServicesInFarm $farm
  1. Ralf
    June 18, 2012 at 09:08

    Nice one Nick… thanks for sharing!

  2. August 24, 2012 at 01:01

    Awesome script! Thanks very much. I augmented it to suit my needs as we have 3rd party stuff in our farm (NewsGator Social Sites) that doesn’t take kindly to bouncing the timer service, so threw in an extra function for IISRESET on each server. Thanks again!

  3. Akhilesh Nirapure
    September 11, 2012 at 11:48

    Awesome Nick, i just stumbled upon, it but then i found your blog and the scirpt, i used it as-is and it works, great stuff man.

  4. Ravi Khambhati
    September 15, 2012 at 15:46

    Really helpfull

  5. February 1, 2013 at 13:44

    Excellent script. Thanks for taking the time to publish it

  6. Sachin
    June 21, 2013 at 16:47

    It works great in 2010. But just hangs on waiting for time job to change status in 2013. Anyway to update this thing for 2013.

  7. kakin
    June 28, 2013 at 05:05

    Thanks, you save my life!

  8. Bram Nuyts
    July 18, 2013 at 11:19

    Reblogged this on Bram Nuyts and commented:
    Great script when you need to clear the timer job cache

  9. Tommy rihu
    August 6, 2013 at 11:01

    how often should i run this?

    /Tommy

    • August 8, 2013 at 05:45

      Hi Tommy
      Most people would not need to run this script. It is more likely to be needed during development of a timer job when redeploying the same timer job repeatedly with minor changes until it works. In this scenario you won’t be changing the assembly version each time you make a small change to test so the last version will remain cached and will continue to be used when you deploy any updates until you clear the cache.
      Nick

  10. Derrick Murry
    February 5, 2014 at 18:04

    This is an excellent script. Thanks.

  11. February 7, 2014 at 22:12

    2013 version?

  12. November 21, 2014 at 01:34

    To run this on SharePoint 2013 simply change line 24 from:
    Set-Variable timerServiceName -option Constant -value “SharePoint 2010 Timer”
    to:
    Set-Variable timerServiceName -option Constant -value “SharePoint Timer Service”

  1. September 3, 2012 at 12:56
  2. November 23, 2013 at 02:17
  3. January 20, 2015 at 06:10
  4. May 1, 2015 at 18:57

Leave a comment