All Timer Service Servers in a farm should be in the same time zone
http://go.microsoft.com/fwlink/?LinkId=247106
Target | Microsoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm | ||
Parent Monitor | System.Health.ConfigurationState | ||
Category | Alert | ||
Enabled | True | ||
Alert Generate | True | ||
Alert Severity | Warning | ||
Alert Priority | Normal | ||
Alert Auto Resolve | True | ||
Monitor Type | Microsoft.KnowledgeServices.Library.PowerShellMonitorEx | ||
Remotable | True | ||
Accessibility | Public | ||
Alert Message |
| ||
RunAs | Microsoft.SharePoint.Foundation.2010.AdminAccount | ||
Comment | SupportTopic=TBD;VersionNumber=1.0.0.0; |
<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>
[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
{
& $mainScriptBlock
}
# set the output
$mom = new-object -comobject "MOM.ScriptAPI"
$bag = $mom.CreatePropertyBag()
if ($scriptoutput.TimerServiceInSync -ne $null)
{
$bag.AddValue("TimerServiceInSync", $scriptoutput.TimerServiceInSync)
}
$bag
</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>