I’m pleased to announce the availability of v1.09 of the Test-ExchangeServerHealth.ps1 script.

This version of the script contains one minor bug fix for database availability group member replication health reporting in mixed Exchange 2010/2013 organizations.

The issue that is fixed was an error when running Test-ReplicationHealth from an Exchange 2013 server against an Exchange 2010 server. Little bugs like this have appeared before in the Test-* cmdlets that ship with Exchange 2013. I fix them as best I can but there is clearly going to be more long term benefit in leveraging Managed Availability in future scripts, as I mentioned here. Still, as long as I am able to I will keep patching the scripts to work in as many on-premises organizations as possible.

Here is an example of Test-Replicationhealth run against an Exchange 2013 server and then an Exchange 2010 server.

[PS] C:\>Test-ReplicationHealth ex2013srv1

Server          Check                      Result     Error
------          -----                      ------     -----
EX2013SRV1      ClusterService             Passed
EX2013SRV1      ReplayService              Passed
EX2013SRV1      ActiveManager              Passed
EX2013SRV1      TasksRpcListener           Passed
EX2013SRV1      TcpListener                Passed
EX2013SRV1      ServerLocatorService       Passed
EX2013SRV1      DagMembersUp               Passed
EX2013SRV1      ClusterNetwork             Passed
EX2013SRV1      QuorumGroup                Passed
EX2013SRV1      DatabaseRedundancy         Passed
EX2013SRV1      DatabaseAvailability       Passed
EX2013SRV1      DBCopySuspended            Passed
EX2013SRV1      DBCopyFailed               Passed
EX2013SRV1      DBInitializing             Passed
EX2013SRV1      DBDisconnected             Passed
EX2013SRV1      DBLogCopyKeepingUp         Passed
EX2013SRV1      DBLogReplayKeepingUp       Passed

[PS] C:\>Test-ReplicationHealth ho-ex2010-mb1
Could not load file or assembly 'Microsoft.Exchange.Data, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
    + CategoryInfo          : NotSpecified: (:) [Test-ReplicationHealth], FileNotFoundException
    + FullyQualifiedErrorId : [Server=EX2013SRV1,RequestId=a14edcd8-cd42-4cb3-9af7-0140d97babef,TimeStamp=7/07/2014 12
   :52:02 PM] [FailureCategory=Cmdlet-FileNotFoundException] 864218C8,Microsoft.Exchange.Monitoring.TestReplicationHe
  alth
    + PSComputerName        : ex2013srv1.exchangeserverpro.net

To work around this issue I’ve added a function to the script that will detect the error and create a PSSession to an Exchange 2010 CAS in the same site as the mailbox server that Test-ReplicationHealth is being run against. The test can then be performed by the Exchange 2010 server instead.

[PS] C:ScriptsTestReplicationHealth>.Test-E14ReplicationHealth.ps1 ho-ex2010-mb1 -Verbose
VERBOSE: Get replication health for ho-ex2010-mb1
VERBOSE: Error, trying workaround
VERBOSE: Creating PSSession for HO-EX2010-MB1.exchangeserverpro.net
VERBOSE: Using URL http://ho-ex2010-mb1.exchangeserverpro.net/powershell
VERBOSE: Running replication health test on ho-ex2010-mb1
VERBOSE: Removing PSSession
VERBOSE: ClusterService Passed
VERBOSE: ReplayService Passed
VERBOSE: ActiveManager Passed
VERBOSE: TasksRpcListener Passed
VERBOSE: TcpListener Passed
VERBOSE: ServerLocatorService Passed
VERBOSE: DagMembersUp Passed
VERBOSE: ClusterNetwork Passed
VERBOSE: QuorumGroup Passed
VERBOSE: FileShareQuorum Passed
VERBOSE: DBCopySuspended Passed
VERBOSE: DBCopyFailed Passed
VERBOSE: DBInitializing Passed
VERBOSE: DBDisconnected Passed
VERBOSE: DBLogCopyKeepingUp Passed
VERBOSE: DBLogReplayKeepingUp Passed

Here is the sample code. Note that this is for demonstration purposes and is not intended to be a working script. The function has been incorporated into Test-ExchangeServerHealth.ps1.

#requires -version 2

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

#This function is used to test replication health for Exchange 2010 DAG members in mixed 2010/2013 organizations
Function Test-E14ReplicationHealth()
{
	param ( $e14mailboxserver )

	$e14replicationhealth = $null

    $ADSite = (Get-ExchangeServer $e14mailboxserver).Site
    $e14cas = (Get-ExchangeServer | where {$_.IsClientAccessServer -and $_.AdminDisplayVersion -match "Version 14" -and $_.Site -eq $ADSite} | select -first 1).FQDN

	Write-Verbose "Creating PSSession for $e14cas"
    $url = (Get-PowerShellVirtualDirectory -Server $e14cas -AdPropertiesOnly | Where {$_.Name -eq "Powershell (Default Web Site)"}).InternalURL.AbsoluteUri
    if ($url -eq $null)
    {
        $url = "http://$e14cas/powershell"
    }

    Write-Verbose "Using URL $url"

	try
	{
	    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $url -ErrorAction STOP
	}
	catch
	{
	    Write-Verbose "Something went wrong"
		if ($Log) {Write-Log $_.Exception.Message}
    	Write-Warning $_.Exception.Message
	}

	try
	{
	    Write-Verbose "Running replication health test on $e14mailboxserver"
	    $e14replicationhealth = Invoke-Command -Session $session {Test-ReplicationHealth} -ErrorAction STOP
	}
	catch
	{
	    Write-Verbose "An error occurred"
		if ($Log) {Write-Log $_.Exception.Message}
	    Write-Warning $_.Exception.Message
	}

	Write-Verbose "Removing PSSession"
	Remove-PSSession $session.Id

	return $e14replicationhealth
}

try
{
    Write-Verbose "Get replication health for $server"
    $replicationhealth = $server | Invoke-Command {Test-ReplicationHealth -ErrorAction STOP} 
}
catch
{
    Write-Verbose "Error, trying workaround"
    $replicationhealth = Test-E14ReplicationHealth $server
}

foreach ($healthitem in $replicationhealth)
{
    $tmpstring = "$($healthitem.Check) $($healthitem.Result)"
	Write-Verbose $tmpstring
	if ($Log) {Write-Logfile $tmpstring}
}

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. Byron Coetzee

    I am trying to download the script and it says that the page is not found when clicking on the link…

    Has it been moved?

  2. nik

    hi paul

    great script by the way! ive just upgraded to 2013 CU12.
    I also added a 4th DAG member server that has no active databases on it.
    when your script runs it exits after “mail flow test” without doing any of the database checking. Is this because there are no active databases on the last server that was checked? I cant figure out why its not working. there is no error. it just says —-finishing and then ends. odd! was working up until I updated to CU12

    thanks
    nik

  3. Alessandro Bergo

    I have the same issue as Sam_in:

    Mail flow test: WARNING: Connecting to remote server xxx.xxxxx.xx failed with the following error message : WinRM
    cannot process
    the request. The following error occurred while using Kerberos authentication: Cannot find the computer
    xxx.xxxxx.xx. Verify that the computer exists on the network and that the name provided is spelled correctly.
    For more information, see the about_Remote_Troubleshooting Help topic.
    WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Provide an argument that is
    not null or empty, and then try the command again.
    Remove-PSSession : Cannot validate argument on parameter ‘Id’. The argument is null. Provide a valid value for the
    argument, and then try running the command again.
    At C:ScriptsTest-ExchangeServerHealth_V1.14Test-ExchangeServerHealth.ps1:425 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

    I use PowerShell virtual directory URLs configured with DNS alias.

  4. Sam_in

    If no active databases in the server , i’m getting the result no active databases. I’m getting the error and warning where the active databases are located.

    1. Paul Cunningham

      Which CU are your servers at? I had some feedback overnight from another person who upgraded to CU8 and it solved some issues with the script for them.

      1. Sam_in

        We are having Exchange 2013 SP1 (aka CU4) .

        1. Paul Cunningham

          I recommend you upgrade then, as you’re running on an unsupported version.

  5. Sam_in

    PowerShell virtual directory URLs have the server’s FQDN. Getting this error if i move the database to another server. Not sure how to fix this.

    1. Paul Cunningham

      The test might fail if there’s no active databases on the server at the time.

      As it stands right now that part of the script is a bit of a hack for 2013. I am hoping to do something more reliable in the next version.

  6. Sam_in

    Great Script. Works good in exchange 2013.

    One small query. Always Test mail flow is failing since we are using loadbalancer in the frontend.

    can you tell how it can be resolved?

      1. Sam_in

        nope. The Netscalar loadbanacer is loadbalacing email traffic as well doing optimization. The following error occured. ” WinRM cannot
        rocess the request. The following error occurred while using Kerberos authentication: Cannot find the computer”. This mail flow is checking netscalar VIP address and obviously this computer account is not available in AD. Hope this explains about my issue.

        Can you tell me how to fix this issue?

        1. Sam_in

          above one is warning and then i got the below error.

          “Remove-PSSession : Cannot validate argument on parameter ‘Id’. The argument is null. Provide a valid value for the
          argument, and then try running the command again.
          At c:Test-ExchangeServerHealth.ps1:424 char:19
          + Remove-PSSession $session.Id
          + ~~~~~~~~~~~
          + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
          + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

          Fail”

        2. Paul Cunningham

          Do your PowerShell virtual directory URLs have the server’s FQDN in them or a DNS alias?

  7. Jo

    Wonderful script. Works great so far and I’ve placed it into my daily/weekly maintenance routine. Only question i have is why the PF DBs Mounted is n/a? Is it because 2013 uses mailbox as your PF and your script is reporting from older versions of exchange?

    Thanks

    1. Paul Cunningham

      Correct, 2013 has no public folder databases, so they will always be N/A for a 2013-only environment.

  8. Barend

    Good Day, This is a great script. good job.
    I have applied this to numurous Exchange 2010 servers and it works great. Thank you.

    I have a older version of Exchange that I need to monitor (2007 – yes I know it is old 🙂 ).

    the Get-Exhchangeserver cmdlet does not work on exchange 2007. Is there a workaround to apply this scirpt to a 2007 installation?

    1. Paul Cunningham

      Get-ExchangeServer cmdlet is available in Exchange 2007 as well. But I don’t have any Exchange 2007 systems I can use to work out how to get the script working on that version any more.

  9. Ryan

    Hi Paul –

    As we are just introducing Exchange 2013 into our on-prem 2010 environment, I decided to try out the latest version of this script to see how it would run. I was running this on an Exchange 2013 server and I kept seeing the following error (once for each 2010 Mailbox server):

    “WARNING: Server does not have the Mailbox server role installed. The Test-ReplicationHealth cmdlet can be run only from a Mailbox server, or from a non-Mailbox server when specifying a Mailbox server as a target.”

    We currently have our 2010 environment roles separated (combined CAS/HUB w/ separate Mailbox). I took a look at the new function you added for testing replication health against a 2010 mailbox server and ended up changing this line:

    $e14replicationhealth = Invoke-Command -Session $session {Test-ReplicationHealth} -ErrorAction STOP

    To this:

    $e14replicationhealth = Invoke-Command -Session $session -Args $e14mailboxserver.Name {Test-ReplicationHealth $args[0]} -ErrorAction STOP

    and it appeared to start working as expected.

    I can see where the original Invoke-Command would run without the warning if CAS and Mailbox roles were combined but, would it test the replication health of the intended mailbox server or just the CAS/MBX that is represented by $session?

    1. Paul Cunningham

      Good catch. I suspect you are right and I have not implemented that correctly. I’ll roll your fix into the next version. Thanks!

  10. Bill

    Thanks for all the work you do for us administrators. Script works great.

    Bill

Leave a Reply