AK562002

Monitor_AK562002 (UnitMonitor)

All Timer Service Servers in a farm should be in the same time zone

Knowledge Base article:

External

http://go.microsoft.com/fwlink/?LinkId=247106

Element properties:

TargetMicrosoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm
Parent MonitorSystem.Health.ConfigurationState
CategoryAlert
EnabledTrue
Alert GenerateTrue
Alert SeverityWarning
Alert PriorityNormal
Alert Auto ResolveTrue
Monitor TypeMicrosoft.KnowledgeServices.Library.PowerShellMonitorEx
RemotableTrue
AccessibilityPublic
Alert Message
All Timer Service Servers in a farm should be in the same time zone
<Details>
<Content>
All servers that run the foundation timer service in a farm should be in the same time zone. If they are in different time zones then there can be timing issues. It is best to have all servers configured to run in the same time zone (it is not required to physically be in the same time zone).

For more information about this known issue, see the Knowledge Base article.
</Content>
<CollectedInformation>
<Info>
<Name>Farm Name</Name>
<Value>{0}</Value>
</Info>
<Info>
<Name>All Timer Service Servers are in Same Time Zone</Name>
<Value>{1}</Value>
</Info>
</CollectedInformation>
</Details>
RunAsMicrosoft.SharePoint.Foundation.2010.AdminAccount
CommentSupportTopic=TBD;VersionNumber=1.0.0.0;

Source Code:

<UnitMonitor ID="Monitor_AK562002" Comment="SupportTopic=TBD;VersionNumber=1.0.0.0;" Accessibility="Public" Enabled="true" Target="MicrosoftKnowledgeServicesSharePointFoundation2010Library!Microsoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm" ParentMonitorID="Health!System.Health.ConfigurationState" Remotable="true" Priority="Normal" RunAs="MicrosoftSharePointFoundation2010!Microsoft.SharePoint.Foundation.2010.AdminAccount" TypeID="KnowledgeServicesLibrary!Microsoft.KnowledgeServices.Library.PowerShellMonitorEx" ConfirmDelivery="true">
<Category>Alert</Category>
<AlertSettings AlertMessage="MonitorMessage073dbf658298448b8f7c515aed46232c">
<AlertOnState>Error</AlertOnState>
<AutoResolve>true</AutoResolve>
<AlertPriority>Normal</AlertPriority>
<AlertSeverity>Warning</AlertSeverity>
<AlertParameters>
<AlertParameter1>$Target/Property[Type="MicrosoftKnowledgeServicesSharePointFoundation2010Library!Microsoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm"]/FarmName$</AlertParameter1>
<AlertParameter2>$Data/Context/Property[@Name='TimerServiceInSync']$</AlertParameter2>
</AlertParameters>
</AlertSettings>
<OperationalStates>
<OperationalState ID="Success" MonitorTypeStateID="Success" HealthState="Success"/>
<OperationalState ID="Error" MonitorTypeStateID="Error" HealthState="Error"/>
</OperationalStates>
<Configuration>
<ScriptName>AK562002.ps1</ScriptName>
<Parameters/>
<ScriptBody><Script>
[ScriptBlock]$mainScriptBlock = {

$ErrorActionPreference = "Stop"

# Set up the arguments
$scriptargs = new-object psobject

# Set up the output
$global:scriptoutput = new-object psobject
$scriptoutput | add-member NoteProperty "TimerServiceInSync" $false
#-----------------------------------------------------
# MAIN CODE SECTION
#-----------------------------------------------------

function Handle-Errors([string]$ErrMsg)
{
if (! $error)
{
return;
}
$ErrorString = $ErrMsg;

$EventLog_Format = "`nCurrent PID: {0}`nInvocationInfo.MyCommand: {1}`nInvocationInfo.ScriptLineNumber: {2}`nInvocationInfo.OffsetInLine: {3}`nInvocationInfo.ScriptName: {4}`nInvocationInfo.Line: {5}`nInvocationInfo.PositionMessage: {6}`nInvocationInfo.InvocationName: {7}`nInvocationInfo.PipelineLength: {8}`nInvocationInfo.PipelinePosition: {9}`n";

$EventLog_Template = "[{0} in Advisor script] {1} {2}";
$Exception = $error[$error.Count - 1];
if ($Exception.InvocationInfo -ne $null)
{
$ErrorString += ($EventLog_Format -f $pid, $Exception.InvocationInfo.MyCommand,
$Exception.InvocationInfo.ScriptLineNumber, $Exception.InvocationInfo.OffsetInLine, $Exception.InvocationInfo.ScriptName,
$Exception.InvocationInfo.Line, $Exception.InvocationInfo.PositionMessage, $Exception.InvocationInfo.InvocationName,
$Exception.InvocationInfo.PipelineLength, $Exception.InvocationInfo.PipelinePosition);
}

if ($null -ne $Exception.Exception)
{
$Exception = $Exception.Exception;
}
$InnerException = $Exception;
if ($null -ne $Exception.InnerException)
{
$InnerException = $Exception.InnerException;
}

$EventObject = New-Object Diagnostics.EventLog;
$EventObject.Source = "Operations Manager"
$EventObject.WriteEntry(($EventLog_Template -f $InnerException.GetType().FullName, $ErrorString, $Exception.Message), [System.Diagnostics.EventLogEntryType]::Error, 8000);
$error.Clear();
}

Function IsSharePointExtensionInstalled
{
$isInstalled = $true
# Loads the SharePoint 2010 PowerShell extensions so we can easily
# get a reference to our dlls.
try
{
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
}
catch
{
$isInstalled = $false
}
$Error.Clear()
return $isInstalled
}

#-----------------------------------------------------
# Helper function to verify that all the supplied servers are in sync
#-----------------------------------------------------
Function Get-ServersInSync
{
PARAM($ServersToCheck = $null)
$inSync = $true

if($ServersToCheck -ne $null)
{
# We've only got a single server - not need to keep going. We're good
if($ServersToCheck.Count -ne $null)
{
# The first one in the list will be our "golden" server
$baseline = $ServersToCheck[0]
for($i=1; $i -lt $ServersToCheck.Count; $i++)
{
if (($ServersToCheck[$i].TimeZone -ne "") -and ($baseline.TimeZone -ne ""))
{
if($baseline.TimeZone -ne $ServersToCheck[$i].TimeZone)
{
$inSync = $false
break
}
}
}
}
}
return $inSync
}

#-----------------------------------------------------
# Helper function to get the servers running timer service.
#-----------------------------------------------------
Function Get-TimerServiceServers
{
PARAM($FarmServers)

#create array
$serversRunningTimerService = @()

#loop through each server. Get instances that have Timer service and is online.
foreach($server in $FarmServers)
{
#boolean weather or not the server runs central admin
[bool]$containsTimerServiceInstance = ($server.ServiceInstances |
Where-Object {$_.TypeName -eq "Microsoft SharePoint Foundation Timer"}
) -ne $null

if($containsTimerServiceInstance)
{
if (($server | Get-Member -Name "TimeZone") -eq $null)
{
try
{
#Get Time Zone info, format and add to SPServer object
$tz = Get-WmiObject -Class Win32_TimeZone -ComputerName $server.Address -ErrorAction SilentlyContinue
$TimeZone = $tz.Caption.Replace("GMT","UTC")
$server | Add-Member -MemberType NoteProperty -Name "TimeZone" -Value $TimeZone
}catch{
$server | Add-Member -MemberType NoteProperty -Name "TimeZone" -Value ""
}
#$Error.Clear()
}

#add server to array
$serversRunningTimerService += $server

}

}
return $serversRunningTimerService
}

#-----------------------------------------------------
# Main Discovery
#-----------------------------------------------------

function AdvisorRule($scriptargs, $scriptoutput)
{
Try
{
$timerServersAreInSync = $true
#Get the farm and the servers and solutions in the farm
if ((IsSharePointExtensionInstalled) -eq $true)
{
$SPFarm = [Microsoft.SharePoint.Administration.SPFarm]::Local
}

if ($SPFarm -ne $null)
{
$ServersInFarm = $SPFarm.Servers
[bool]$timerServersAreInSync = $true

$TimerServiceServers = @(Get-TimerServiceServers -FarmServers $ServersInFarm)

#Verify timer servers are in sync

$timerServersAreInSync = Get-ServersInSync -ServersToCheck $TimerServiceServers
$scriptoutput.TimerServiceInSync = $timerServersAreInSync
}
}
Catch
{
Handle-Errors "AK562002"
}

}
AdvisorRule $scriptargs $scriptoutput

}

Function Test-NeedPSRemoting
{
$script:SharePointPSVer = 0
$registryKey2010 = "HKLM:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0"
$registryKey2013 = "HKLM:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0"

if (Test-Path -Path $registryKey2010)
{
if ((Get-ItemProperty -Path $registryKey2010 -ErrorAction SilentlyContinue).Sharepoint -eq "Installed")
{
$script:SharePointPSVer = 2010
}
}
if (Test-Path -Path $registryKey2013)
{
if ((Get-ItemProperty -Path $registryKey2013 -ErrorAction SilentlyContinue).Sharepoint -eq "Installed")
{
$script:SharePointPSVer = 2013
}
}

$PSCLRVersion = [System.String]::Format("{0}.{1}", $PSVersionTable.CLRVersion.Major, $PSVersionTable.CLRVersion.Minor)
if (($PSCLRVersion -ieq "2.0") -and ($script:SharePointPSVer -ieq 2013))
{
return $true
}
return $false
}

if ((Test-NeedPSRemoting))
{
[bool]$script:psRemotingEnabled = $false
# Enable PowerShell Remoting need elevated BUILTIN\Administrators privilege
$winRMService = (Get-Service WinRM -ErrorAction SilentlyContinue)
if ($winRMService -ne $null)
{
if ($winRMService.Status -ieq [System.ServiceProcess.ServiceControllerStatus]::Stopped)
{
$winRMService.Start()
$winRMService.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Running, [System.TimeSpan]::FromSeconds(15))
}
$psSessionConfiguration = (Get-PSSessionConfiguration -Name "Microsoft.PowerShell" -ErrorAction SilentlyContinue)
if ($psSessionConfiguration.Permission.Contains("BUILTIN\Administrators AccessAllowed"))
{
$script:psRemotingEnabled = $true
}
}

# Call remote PS session when PSRemoting is enabled.
if ($script:psRemotingEnabled -eq $true)
{
$session = New-PSSession
Invoke-Command -Session $session -ScriptBlock $mainScriptBlock
$global:scriptoutput = Invoke-Command -Session $session -ScriptBlock {$global:scriptoutput}
Remove-PSSession -Session $session
}
}
else
{
&amp; $mainScriptBlock
}

# set the output
$mom = new-object -comobject "MOM.ScriptAPI"
$bag = $mom.CreatePropertyBag()

if ($scriptoutput.TimerServiceInSync -ne $null)
{
$bag.AddValue("TimerServiceInSync", $scriptoutput.TimerServiceInSync)
}

$bag

</Script></ScriptBody>
<SnapIns/>
<TimeoutSeconds>300</TimeoutSeconds>
<Schedule>29615</Schedule>
<ErrorExpression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Boolean">Property[@Name='TimerServiceInSync']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Boolean">false</Value>
</ValueExpression>
</SimpleExpression>
</ErrorExpression>
<SuccessExpression>
<Not>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Boolean">Property[@Name='TimerServiceInSync']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="Boolean">false</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</Not>
</SuccessExpression>
</Configuration>
</UnitMonitor>