Tuesday, December 22, 2015

Event ID 6398 SharePoint Configuration Cache Out-dated Powershell

Sometimes an event with ID 6398 is logged in the Windows Application log. This is usually due to the configuration cache being outdated. So you need to perform some steps on the SharePoint server to force a rebuild of the configuration cache.

The cache goes by many names; file system cache, configuration cache, object cache, bunch of XML files and on and on. What this cache really is though is a cache of the farm configuration database objects. Since most things in SharePoint are objects and all SharePoint servers in a farm need to know information on these objects, it makes sense to cache this information locally on each server to save on database round trips. But like any cache this information can become stale or incorrect for many reasons. Usually this is caused by a change made on 1 SharePoint server in the farm not being written to the configuration database, either because of SQL timeouts, the SQL stored procedure did not complete, the SharePoint server is at a different version level than the rest of the farm, the list goes on.

Therefore clearing the cache is sometimes needed to get all of the SharePoint servers up to date on the latest farm information. This involves shutting down the SharePoint Timer service on all of the machines and deleting all of the XML files in the %ALLUSERSPROFILE%\Microsoft\SharePoint\Config\<GUID>. Opening the cache.ini file in Notepad.exe and changing whatever value is present to 1; then starting the SharePoint Timer service again on each server in the farm. During this process no timer jobs will be ran obviously, but the sites that SharePoint is hosting will be available barring any major catastrophic problem.

There is a timer job called Config Refresh on ever SharePoint farm which runs every 15 seconds and updates the cache on all of the SharePoint servers in the farm. When the XML file for an object does not exist on a server a new XML file is created with the current information from the SharePoint’s farm configuration database.

So long story short; clearing the cache is sometimes needed when there may be inaccurate information in a SharePoint server’s persisted object cache and clearing this cache is most likely safe to perform at any time

Script source: https://spcachecleaner.codeplex.com/


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

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

#**************************************************************************************
# Functions
#**************************************************************************************
#<summary>
# Loads the SharePoint Powershell Snapin.
#</summary>
Function Load-SharePoint-Powershell
{
If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
{
    Write-Host -ForegroundColor White " - Loading SharePoint Powershell Snapin"
Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Stop
}
}

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

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
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 "Name='$timerServiceName'"
sc.exe \\$serverName stop $timerServiceName > $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 "Name='$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($farm)
{
Write-Host ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
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 "Name='$timerServiceName'"
sc.exe \\$serverName start $timerServiceName > $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($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)
{
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($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)
{
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
#**************************************************************************************

# Load SharePoint Powershell Snapin
Load-SharePoint-Powershell

# Get the local farm instance
$farm = Get-SPServer | where {$_.Role -match "Application"}

# 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

Re-provision SharePoint Service Applications Powershell

# Re-provisions all the SharePoint Web Services (Resolves STS errors)

$h = Get-SPServiceHostconfig

$h.Provision()

$services = Get-SPServiceApplication

foreach ($service in $services) { $service.provision();
write-host $service.name}

PSCONFIG Steps

The following are the steps PSCONFIG initiates on each server from which it is run. Keep in mind it only performs the actions necessary for the particular server as defined in the config.db
  1. Initialize SharePoint products and technologies configuration
  2. Create Configuration database.
  3. Install help collections
  4. Secure SharePoint resources
  5. Register SharePoint Services (install)
  6. Register SharePoint features (install)
  7. Provision Central Administration Web application and site
  8. Register SharePointHealth Analysis rules (installs)
  9. Create sample data and provision default Web application
  10. Install application content files
  11. Finalize SharePoint product and technologies configuration