Exchange 2013 Test-ServiceHealth Doesn’t Work for Client Access Servers

I’m a big fan of the PowerShell test cmdlets that ship with Exchange Server, so much so that I’ve written a script that makes use of many of them to produce an Exchange Server health report.

So I am a little frustrated to discover that the Test-ServiceHealth cmdlet produces some unexpected output when run against a remote Exchange 2013 server that is installed only with the Client Access server role.

To demonstrate, here is the CAS-only server running in my test lab.

[PS] C:\>Get-ExchangeServer E15FSW | Select ServerRole

ServerRole : ClientAccess

Here is the Test-ServiceHealth output if I run Test-ServiceHealth against that server.

[PS] C:\>Test-ServiceHealth -Server E15FSW
There are no Microsoft Exchange 2007 server roles installed
on E15FSW.exchange2013demo.com.
    + CategoryInfo          : InvalidArgument: (:) [Test-ServiceHealth],
NoExchangeRoleInstalledException + FullyQualifiedErrorId
: [Server=E15MB1,RequestId=d43bba01-2a19-42b1-a380-ecd19d6f271d,
TimeStamp=22/08/2013 10:41:09 AM] 9E9BF046,
Microsoft.Exchange.Monitoring.TestServiceHealth
+ PSComputerName : e15fsw.exchange2013demo.com

Of course this error text stands out immediately.

There are no Microsoft Exchange 2007 server roles installed…

But a quick read of the rest of the error indicates what the problem may actually be.

Server=E15MB1

It appears that my CAS (E15FSW) is proxying the test to one of the mailbox servers. When you consider the role of Client Access in Exchange 2013 as a “a thin and stateless server” that provides “proxy services” I guess that makes sense.

That said, I still have the problem of an annoying bug in my script that needs a solution. So I’ve put together this proof of concept code which I am going to incorporate into the next version of Test-ExchangeServerHealth.ps1 that uses WMI instead of the Test-ServiceHealth cmdlet to assess the health of the services on an Exchange 2013 Client Access server.

Note this is proof of concept only, you can take this code and use it however you like but it is not yet intended to be a functional script.

#Proof of concept code to test service
#health on E15 CAS-only servers

[CmdletBinding()]
param (
	[Parameter( Mandatory=$false)]
	[string]$Server
)

$servicesrunning = @()
$servicesnotrunning = @()
$casservices = @(
	"IISAdmin",
	"W3Svc",
	"WinRM",
	"MSExchangeADTopology",
	"MSExchangeDiagnostics",
	"MSExchangeFrontEndTransport",
	"MSExchangeHM",
	"MSExchangeIMAP4",
	"MSExchangePOP3",
	"MSExchangeServiceHost",
	"MSExchangeUMCR"
	)

try {
	$servicestates = @(Get-WmiObject -ComputerName $server -Class Win32_Service -ErrorAction STOP | where {$casservices -icontains $_.Name} | select name,state,startmode)
}
catch
{
	Write-Warning $_.Exception.Message
	EXIT
}

Write-Verbose "$($servicestates.count) services found"

$servicesrunning = @($servicestates | Where {$_.StartMode -eq "Auto" -and $_.State -eq "Running"})
$servicesnotrunning = @($servicestates | Where {$_.Startmode -eq "Auto" -and $_.State -ne "Running"})

if ($($servicesnotrunning.Count) -gt 0)
{
	Write-Host -ForegroundColor Red "Service health check failed"
    Write-Host -ForegroundColor Red "Services not running:"
    foreach ($service in $servicesnotrunning)
    {
        Write-Host -ForegroundColor Red "- $($service.Name)"	
    }
}
else
{
	Write-Host -ForegroundColor Green "Service health check passed"
}

Here is an example of a pass and fail result.

PS C:\scripts> .\Test-E15CASServiceHealth.ps1 -Server E15FSW -Verbose
VERBOSE: 11 services found
Service health check passed

PS C:\scripts> .\Test-E15CASServiceHealth.ps1 -Server E15FSW -Verbose
VERBOSE: 11 services found
Service health check failed
Services not running:
- MSExchangeHM
About Paul Cunningham

Paul is a Microsoft Exchange Server MVP and publisher of Exchange Server Pro. He also holds several Microsoft certifications including for Exchange Server 2007, 2010 and 2013. Connect with Paul on Twitter and Google+.

Leave a Comment

*

We are an Authorized DigiCert™ SSL Partner.