When developing a timer job for SharePoint using Visual Studio, it is usually necessary to repeatedly redeploy the same solution multiple times during development until all the issues are figured out and fixed.
The problem with solutions containing timer jobs is that, if the timer job cache is not cleared across all servers in the farm, the timer job may continue running code from an older assembly which has been uninstalled but simply remained cached.
This situation is nightmarish for software development because if you don’t know about the timer job cache, you may forever keep pulling your hair out since your new/updated code simply refuses to execute… or at best, executes inconsistently.
The PowerShell script below, will help in such situations. It clears the timer job cache for all servers in the farm which have the timer service installed and saves you the hassle of manually clearing the cache after each solution redeployment or update.
NOTE 1: This script can be run on any server in a multi-server SharePoint farm. But it needs to be executed by a farm administrator.
NOTE 2: The SharePoint timer job cache is also often called the SharePoint Configuration Cache… So no confusion there.
The script
# 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 # If on a SharePoint 2013 environment, just change the below value to "SharePoint Timer Service"" #************************************************************************************** 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
Here are the steps performed by the above script. Each step is performed on each server in the farm which has the timer service installed before going to the next step.
- Stop the “SharePoint 2010 Timer” service (or the “SharePoint Timer Service” if you’re on a SharePoint 2013 farm).
Note: For SharePoint 2013, change line 18 to:Set-Variable timerServiceName -option Constant -value "SharePoint Timer Service"
- Delete all the XML files in the config cache.
- Edit the “cache.ini” file in the same folder that contained the XML files, and set the content to “1” (without the quotes).
This means all cache settings need to be refreshed. This value eventually gets updated to another number when the cache is repopulated. - Start the “SharePoint 2010 Timer” service (or the “SharePoint Timer Service” for a 2013 farm).
Hello big bros,how are you? I hope fine,I guess you are into website development and design, can I collaborate with you? I want to develope a website, tittle http://www.ibomtour.com.ng,it is to promote the tourism sector of Akwa Ibom and Cross Rivers state, it will generate money, I have details but no money to do so and I want to send the proposal to Akwa Ibom State governor this month and I wanted the website to be one of the proposal, can you design then a percentage which the business is generating will be yours,I look forward to hearing from you.