AKN675163

Monitor_AKN675163 (UnitMonitor)

Checks if there are more than 20 SharePoint web applications per farm

Knowledge Base article:

External

http://go.microsoft.com/fwlink/?linkid=400536

Element properties:

TargetMicrosoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm
Parent MonitorSystem.Health.ConfigurationState
CategoryAlert
EnabledTrue
Alert GenerateTrue
Alert SeverityError
Alert PriorityHigh
Alert Auto ResolveTrue
Monitor TypeMicrosoft.KnowledgeServices.Library.PowerShellMonitorEx
RemotableTrue
AccessibilityPublic
Alert Message
Checks if there are more than 20 SharePoint web applications per farm
<Details>
<Content>The number of Web Applications exceeds the supported limit of 20 web applications per farm.</Content>
<CollectedInformation />
</Details>
RunAsDefault
CommentSupportTopic=TBD;VersionNumber=1.0.0.0;

Source Code:

<UnitMonitor ID="Monitor_AKN675163" 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="High" TypeID="KnowledgeServicesLibrary!Microsoft.KnowledgeServices.Library.PowerShellMonitorEx" ConfirmDelivery="true">
<Category>Alert</Category>
<AlertSettings AlertMessage="MonitorMessage25a08dc100e94c43a4f06977deb14a8a">
<AlertOnState>Error</AlertOnState>
<AutoResolve>true</AutoResolve>
<AlertPriority>High</AlertPriority>
<AlertSeverity>Error</AlertSeverity>
</AlertSettings>
<OperationalStates>
<OperationalState ID="Success" MonitorTypeStateID="Success" HealthState="Success"/>
<OperationalState ID="Error" MonitorTypeStateID="Error" HealthState="Error"/>
</OperationalStates>
<Configuration>
<ScriptName>AKN675163.ps1</ScriptName>
<Parameters>
<Parameter>
<Name>SharePointVersion</Name>
<Value>$Target/Property[Type="MicrosoftKnowledgeServicesSharePointFoundation2010Library!Microsoft.KnowledgeServices.SharePoint.Foundation.2010.SPFarm"]/SPMajorVersion$</Value>
</Parameter>
</Parameters>
<ScriptBody><Script>PARAM($SharePointVersion)
[ScriptBlock]$mainScriptBlock = {


param($SharePointVersion)

$ErrorActionPreference = "Stop"

# Set up the arguments
$scriptargs = new-object psobject
$scriptargs | add-member NoteProperty "SharePointVersion" $SharePointVersion

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

# Environment
$scriptenv = New-Object System.Management.Automation.PSObject
$scriptenv | Add-Member ScriptProperty "IsSharePoint2013Env" {$scriptargs.SharePointVersion -eq 15}


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 SharePointPSSnapinIsAdded
{
#Initialize $SPPSSnapinIsAdded
$SPPSSnapinIsAdded = $false

# Check if SharePoint 2010 Powershell Snapin is not already added to current session
If (!(Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue))
{

#If SharePoint 2010 Powershell Snapin is not added, add it now.
Add-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue

# Check to confirm SharePoint 2010 Powershell Snapin was added to current session.
If ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -ne $null)
{
$SPPSSnapinIsAdded = $true
}
}

# SharePoint 2010 Powershell Snapin is already added to current session
Else{
$SPPSSnapinIsAdded = $true
}

#Return SharePoint 2010 Powershell Snapin is added to current session true/false
return $SPPSSnapinIsAdded
}

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
}

# Populate-WebAppCache function
#---------------------------------
# Description:
# Populates the $webAppCache array with all SPWebApplication objects in the farm. If $WebAppID is specified,
# populates just the one SPWebApplication object in the $webAppCache having the specified ID
#
# Arguments:
# $WebAppID (Optional) - The GUID of the web application that needs to be populated in the cache. This should be a string in the format 7fb2a0ef-2495-467c-9d69-b2e8afc8b17c
# $AssignmentStore (Optional) - The AssignmentStore that should be used when creating the object
#
# Returns:
# None
#
# Owner: TehnoonR
Function Populate-WebAppCache
{
PARAM (
[String]$WebAppID = $null,
[Microsoft.SharePoint.PowerShell.SPAssignmentCollection]$AssignmentStore = $null
)
#If $webAppCache is not null, that means we have already cached all SPWebApplication objects. If WebAppID is not null, we
#will just load the specified SPWebApplication object in the cache
if ($global:webAppCache -ne $null -and $WebAppID.Length -eq 0)
{
return
}
else
{
if (IsSharePointExtensionInstalled)
{
if ($WebAppID.Length -eq 0) #We need to load all SPWebApplications objects of the farm in memory
{
# "Caching all the SPWebApplication objects in the farm" | WriteTo-StdOut
$global:webAppCache = Get-SPWebApplication -IncludeCentralAdministration -AssignmentCollection $AssignmentStore
}
else
{
#We will just load the specified Web Application in the cache, regardless of whether or not it already exists
$global:webAppCache = Get-SPWebApplication -Identity $WebAppID -AssignmentCollection $AssignmentStore
}
}
}
}

#Get-SPWebAppCached function
#---------------------------------
# Description:
# Returns the cached SPWebApplication objects to the caller
#
# Arguments:
# $IncludeCentralAdmin (optional) - A boolean value indicating whether or not central admin web app should be returned. Default value is false
#
# Returns:
# One ore more SPWebApplication objects from $global:webAppCache
#
# Owner: TehnoonR
Function Get-SPWebAppCached
{
PARAM ($IncludeCentralAdmin = $false)
if(SharePointPSSnapinIsAdded -eq $true)
{
Populate-WebAppCache
if ($IncludeCentralAdmin)
{
return $global:webAppCache
}
else
{
return $global:webAppCache | where {$_.IsAdministrationWebApplication -eq $false}
}
}
}

function AdvisorRule($scriptargs, $scriptoutput)
{
Try
{
if($scriptenv.IsSharePoint2013Env)
{
# Initialize parameters
$scriptoutput.HasIssue = $false
# $scriptoutput.SharePointWebAppsCount = 0
$SupportedThreshold_SPWebAppPerFarm = 20

#Lets only count SharePoint Web Apps. IIS Supports many more than 20 web applications
$webApps = Get-SPWebAppCached

if($webApps -ne $null)
{
if($webApps.Count -gt $SupportedThreshold_SPWebAppPerFarm)
{
$scriptoutput.HasIssue = $true
}

# $scriptoutput.SharePointWebAppsCount = $webApps.Count
}
}
}
Catch
{
Handle-Errors "AKN675163"
}

}
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 -ArgumentList @($SharePointVersion)
$global:scriptoutput = Invoke-Command -Session $session -ScriptBlock {$global:scriptoutput}
Remove-PSSession -Session $session
}
}
else
{
&amp; $mainScriptBlock $SharePointVersion
}

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

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

$bag

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