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
Nice one Nick… thanks for sharing!
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!
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.
Really helpfull
Excellent script. Thanks for taking the time to publish it
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.
Thanks, you save my life!
Reblogged this on Bram Nuyts and commented:
Great script when you need to clear the timer job cache
how often should i run this?
/Tommy
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
This is an excellent script. Thanks.
2013 version?
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”