This PowerShell script will perform a health check of your Exchange Server environment, including servers and database availability groups, and output a HTML report that you can send to your inbox.

The report includes a summary of issues that were found, as well as a color-coded table with the detailed test results to help you quickly spot problems.

This is a useful script to run as a daily health check first thing in the morning to identify any problems that may have occurred overnight, and give you a chance to fix them before your end users notice.

powershell-script-health-check-exchange

This script is available to download from the TechNet Script Gallery or Github. Comments are welcome below. If you find a bug please consider raising it as an issue on Github.

Script parameters:

  • -Server, Perform a health check of a single server
  • -ReportMode, Set to $true to generate a HTML report. A default file name is used if none is specified.
  • -ReportFile, Allows you to specify a different HTML report file name than the default.
  • -SendEmail, Sends the HTML report via email using the SMTP configuration within the script.
  • -AlertsOnly, Only sends the email report if at least one error or warning was detected.
  • -Log, Writes a log file to help with troubleshooting.

Examples:

.\Test-ExchangeServerHealth.ps1

Checks all servers in the organization and outputs the results to the shell window.

.\Test-ExchangeServerHealth.ps1 -Server HO-EX2010-MB1

Checks the server HO-EX2010-MB1 and outputs the results to the shell window.

.\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

Checks all servers in the organization, outputs the results to the shell window, a HTML report, and emails the HTML report to the address configured in the script.

If you use the report mode you’ll get a HTML file containing the health check results, and/or an email to your designated address if you also use the send email option.

For the email functionality to work please update these variables in the script to suit your environment.

#...................................
# Modify these Email Settings
#...................................

$smtpsettings = @{
	To =  "administrator@exchangeserverpro.net"
	From = "exchangeserver@exchangeserverpro.net"
	Subject = "Exchange Server Health Report - $now"
	SmtpServer = "smtp.exchangeserverpro.net"
	}
A lot of people ask how to add multiple recipients to the SMTP settings. My advice is to use a distribution group, so that any time you need to modify the list of recipients you can simply change the distribution group membership instead of needing to modify the script code.

When running the script on non-English servers you can modify the following variables in the script to match your language so that the script does not give errors or incorrect results.

#...................................
# Modify these language 
# localization strings.
#...................................

# The server roles must match the role names you see when you run Test-ServiceHealth.
$casrole = "Client Access Server Role"
$htrole = "Hub Transport Server Role"
$mbrole = "Mailbox Server Role"
$umrole = "Unified Messaging Server Role"

# This should match the word for "Success", or the result of a successful Test-MAPIConnectivity test
$success = "Success"

For example, a German system would use the following values:

# The server roles must match the role names you see when you run Test-ServiceHealth.
$casrole = "Clientzugriffs-Serverrolle"
$htrole = "Hub-Transport-Serverrolle"
$mbrole = "Postfachserverrolle"
$umrole = "Unified Messaging-Serverrolle"

# This should match the word for "Success", or the result of a successful Test-MAPIConnectivity test
$success = "Erfolgreich"

Use the ignorelist.txt file to specify the names of any servers, DAGs, or databases that you want to ignore for the tests.

My scheduled task settings for this script are:

  • Run whether user is logged on or not
  • Run with highest privileges
  • Action: Start a program
    • Program: powershell.exe
    • Arguments: -command “C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -Log -SendEmail”

FAQ

Q: Which version of PowerShell is required?

If you are running the script on a server that has Exchange 2010 or 2013 (or later) server roles or management tools installed then it should work.

Q: I’m running multiple versions of Exchange, will the script still work?

Yes, it should work as long as you run it from the highest version of Exchange. For example, in a mixed Exchange 2010/2013 environment you should run the script from an Exchange 2013 server.

Q: Why do I get an error when the script sends the email report?

Make sure you’ve configured the email settings section of the script to point to a Hub Transport that either accepts anonymous users (typically an internet-facing Hub Transport), or if you’re using a separate management server or admin workstation point the SMTP server to a Hub Transport that has a receive connector set up that the server you’re running the script on is allowed to relay through.

Q: Why aren’t Edge Transport servers checked?

Between firewalls and permissions the Edge Transport checks are difficult to account for so they are currently skipped by the script.

Q: What should I do when the script report an error/fail on my servers?

The script doesn’t perform any diagnostics when it detects an error, it only reports them to you. When you see an error you should investigate further using the management tools and cmdlets that are provided by Exchange.

If you are encountering situations where the script reports errors that turn out to be false alarms please let me know and I will do my best eliminate those false alarms.

Q: Can you add feature X to the script?

If you have additional requirements then you are encouraged to customize the script to suit your own needs.

[adrotate banner=”48″]

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. JM

    Hi Guys,

    We are running the script on a 2016 Exchange Server, unfortunately after the last update last week all the MAPI Tests failed. Do you have any idea? If I run the test manually it’s ok.

    Thanks ;-).

  2. Mehmet

    i try to run script from remote a server, how can i run it ?

  3. Muthu

    Hi,

    Thanks for the script. We have deployed 2019 serevrs so it is the same. i have ran the script against the server But it is showing as 2013 only servers as . anything i needto modify

    1. Mehmet

      i try to run script from remote a server, how can i run it ?

  4. Kiran Gandhi

    Hi Paul,
    Thank you for the wonderful script. Is there a way to exclude content index health check because its No longer applicable to Exchange 2019 databases. The report contains the following :-

    Database Availability Group Health Check Summary
    The following DAG errors and warnings were detected.
    Database01- unhealthy content index count is 4 (of 4 )

  5. Dleon

    Hello Paul.

    Amazing script. Very useful to quickly identify what is wrong in big environments

    Is that possible to add Drives capacity and Drive usage percentage with thresholds to be able to predict back pressure?

    Thanks

  6. Srdjan

    Hello,

    Is it possible to run this script as a group managed service account?

    Best regards,
    Srdjan

  7. Tom

    I’m getting the following error and I’ve seen in the comments that others have received this too but didn’t see a specific fix…. Any quick suggestions. We have a loadbalancer that the URL will refer to in the error message below.

    Mail flow test: WARNING: Connecting to remote server outlook.vonbriesen.com failed with the following error message : WinRM cannot process the request. The following error occurred while using
    Kerberos authentication: Cannot find the computer XXXX.XXXXX.com. 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:\Healthcheck\Test-ExchangeServerHealth.ps1:452 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    1. Jose Diaz

      Hi, I had the same error, I am using the same script in the las Exchange 2010 configuration and it work, now using the new Exchange 2016 the mail flow show me a fail test

    2. Eric Brock

      Tom,

      Did you get a fix for this issue? I just added several Exchange 2019 servers to our daily health check script, and they are all failing the mail flow test.

    3. JM

      Same here without solution at the moment, did you find one?

      1. JM

        Hi,

        I was able to adapt the script to make it done.

        – In the “Function Test-E15MailFlow()”, line 409 I “null” the $url :
        – Comment the line that retrieve the url (it force then to use the given url $url = “http://$e15mailboxserver/powershell”) :
        – Running it and it was OK, except for the mailbox server I’m running the script on because it test itself, I then just added a check if I’m on the server running the script to change it

        To resume, the beginning of this function is yet :

        Function Test-E15MailFlow()
        {
        param ( $e15mailboxserver )

        $e15mailflowresult = $null
        $url = $null

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

        if ($e15mailboxserver -eq “server1”)
        {
        $url = “http://server2/powershell”
        Write-Verbose “URL modified from server1 to $url”
        }

        Not that it may not be the cleanest way but it run without problems.

        Sincerely.

  8. Wai Cheng

    Hello Paul,

    Greeting… Great script. I have a question regarding to the ignorelist.txt

    I read from previous comments above the format for ignorelist.txt should be

    server1
    server2
    DB1

    However, the DB I wish the script to ignore in this format

    server1
    Exch DB B (<– contain spaces)

    I tried to add to the the ignorelist.txt but does not work.

    Any suggestions?

    Many thanks in advance,

  9. Prashant N

    Hi,

    We have mixed environment of Exchange 2010 (soon to be decommissioned in DAG) and Exchange 2016 (single server, no DAG, all the mailboxes are moved to O365, serves as a SMTP Server for on-premise applications).

    When I run the script in the PowerShell, I get correct details for all Exchange 2010 Mailboxes, DAG, etc.

    However none of Exchange 2016 related details (Mailbox Databases in EX-16), are part of the HTML report that is sent.

    Is this by design?

    Also can I run the script from a remote machine than running within the EX-16 server?

  10. TFC

    Hi,
    I dont know why I’m getting this error. Any idea?
    PS C:\Program Files\Microsoft\Exchange Server\V15\Scripts> .\new-TestCasConnectivityUser.ps1 -ReportMode -SendEmail

    The only acceptable parameters are in the form of: [-OU ] [-Password ] [-UMDialPlan -UMExtension ].

  11. Bryan Clark

    We applied patches to our server on August 26th and the health check report after that point now says that we Failed the Cluster Network Test. I did a test-cluster and sifted thru the resultant report and only found that it is complaining about us only having one network path. This has always been the case for our Exchange 2016 servers and the test passed before August 26th. Did a Best Practice for Exchange clustering change? or am I missing something?

    1. Bryan Clark

      After Running the cluster Validate the problem seems to have gone away.

  12. mohd khan

    Hi Paul,

    First I would like to appreciate your work and really most of the time we go through your article only in exchange issues. Appreciated your hard work and contribution.

    I want to use this script but when running it getting an error that- Hub transport server role service – failed.

    When executed- test-server health – found EdgeSync service is not running and service status is set automatically.

    When tried to run edge sync service manually getting the following error
    “The Microsoft exchange edge sync service on local computer started and then stopped. some services stop automatically if they are not in use by other services or programs.”

    We don’t have an edge sync server role.
    Please suggest something to skip edge sync service, so that we can get everything in green color in the report.

    Request you to please revert back ASAP, Thanking you in Advance.

  13. Jean-François Harry

    Hi,
    Mail Test Flow is Fail on the report or i have no problem with this.
    All others test are OK.
    My Exchange is in French.
    Is there an option to change ?

  14. Ken Harrell

    Hello. I have upgraded to Exchange 2016 CU 15 and the Activation Preference is no longer showing.

    The line in the script that gets the Activation Preference i is not getting the preference.

    $pref = ($database | Select-Object -ExpandProperty ActivationPreference | Where-Object {$_.Key -ieq $mailboxserver}).Value

    If I run the script using an Exchange 2010 shell is works but not when it is Exchange 2016. Can someone help me fix the script so I get the preference again.

  15. Radhey

    Hi Paul,

    Thanks for such a nice script and it is running fine. But have some queries, i want to skip Public folder checks from the report as we do not have Public folder in our environment.

    Could you please help me on it.

  16. alex

    Hello Thanks for your script i am trying to migrate exchange 2010 to 2016 i get an error that transport Queue fail on the 2016 server.
    Exchange Server Health Check Summary
    The following server errors and warnings were detected.
    • ICUMBXSVR01 – Unified Messaging Server Role required services not running.
    • ICUMBXSVR01 – Transport queue is above high threshold
    Database Availability Group Health Check Summary
    No Exchange DAG errors or warnings.
    Exchange Server Health
    Server Site Roles Version DNS Ping Uptime (hrs) Client Access Server Role Services Hub Transport Server Role Services Mailbox Server Role Services Unified Messaging Server Role Services Transport Queue PF DBs Mounted MB DBs Mounted MAPI Test Mail Flow Test
    EXCHANGE EvolveEast Mailbox, ClientAccess, HubTransport Exchange 2010 Pass Pass 2915 Pass Pass Pass n/a Pass (12) Pass Pass Success Pass
    ICUMBXSVR01 EvolveEast Mailbox Exchange 2016 Pass Pass 735 Pass Pass Pass Fail Fail (7913) n/a Pass Success Pass

  17. Alex

    Hi Paul / everyone,
    Thanks for this script. We’ve been using it on 2010 and it’s been faultless. Just wondering if you could shed some light on an issue with a test on one server:

    We’ve added some 2016 servers to our environment, and we’re now running in full coexistence. The checks on 2010 come back ok, but on the 2016 servers, everything shows as well PASS except for the mailflow check on our first 2016 server, which comes back with:

    Mail flow test: WARNING: Couldn’t perform the operation because the server “xxxx” isn’t a Mailbox server.

    The issue is that the server it references is a CAS server in the 2010 environment. All other 2016 servers pass the test ok.

    Any ideas what’s going on?

    1. Alex

      Found the issue – the internal powershell URL for that server in ECP was mistyped and was pointing to the old CAS server (only 1 letter difference in the name). Problem solved !!

  18. Rodney Huffaker

    Works great with 2016 and below.

    Added this for 2019.
    if ($ExVer -like “Version 15.2*”)
    {
    $version = “Exchange 2019”
    }

    Since indexes are internal, it shows indexes are failed when they just don’t exist externally anymore. Should be a fairly easy thing to change. I’m working through that now.

    1. Franck Ehret

      I’ve just started 2019 migration and noticed that as well… 🙂

      I’ll really appreciate the updated version !

      1. William

        Worked for our Exchange 2019 as well.

  19. Firman Khairul

    hi experts

    how send to multiple email address?

    1. Tim West

      A lot of people ask how to add multiple recipients to the SMTP settings. My advice is to use a distribution group, so that any time you need to modify the list of recipients you can simply change the distribution group membership instead of needing to modify the script code.

  20. Rajkumar

    Warning Occured: he term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, in the exchange server version 2016. Below are the output result.

    [PS] C:\Windows\system32>C:\Scripts\Exchange_Health-Check.ps1
    Initializing…
    —— Checking EXCHANGE-2016
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 74
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 23
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was inclu
    ded, verify that the path is correct and try again.
    Fail
    —— Finishing
    Done.

  21. Muralikrishna Reddy Tekari

    Thanks for the Great Script Paul.

    However I see that the Lagged copies are not properly getting captured and is not writing the correct value for $replaylag variable (I’m on Exchange 2016 CU12)

    I fixed it by editing the right property –
    Old Value – if ($replaylagcopy.Key -ieq $mailboxserver)
    New Value – if ($replaylagcopy.Key.Name -ieq $mailboxserver)

    I think the same applies for the $truncatelag as well.
    New Value – if ($truncationlagcopy.Key.Name -eq $mailboxserver)

  22. fish

    Hello Paul,

    Thanks for your the great script!

    I am using Chinese language in my Windows server 2012, and I don’t understand your script about “localization strings”, do you know how can I set my language?

    Could you please give some tips?

    Thank you!

    1. Raphl Gu

      Add chinese role name like below

      # The server roles must match the role names you see when you run Test-ServiceHealth.
      #英文名称 $casrole = “Client Access Server Role”
      $casrole = “客户端访问服务器角色”
      #英文名称 $htrole = “Hub Transport Server Role”
      $htrole = “集线器传输服务器角色”
      #英文名称 $mbrole = “Mailbox Server Role”
      $mbrole = “邮箱服务器角色”
      # $umrole = “Unified Messaging Server Role”

  23. Mahmoud Atallah

    Dear Paul,

    Thanks a lot for your valuable articles and tips, please can you update the Health Check Script to run with Exchange 2019…
    Current script is not detecting correct Exchange version, also showing warnings on DAG Databases health check as unhealthy content indexes.

    Regards.

  24. Mohan KV

    Hi Paul,

    I want to run the HealthCheck script for our Edge server and also want to provide input file for the list of server. Help me with this.

  25. Mohan KV

    Hi Paul,

    I was run the HealthCheck script for our Edge server and also want to provide input file for the list of server. Help me with this.

  26. Waylon Irons

    Fine way of telling, and good post to obtain data about my presentation topic, which i am going to convey in institution of higher education.

  27. Magnolia Carpentier

    Useful information. Fortunate me I found your website accidentally, and I
    am shocked why this coincidence didn’t came about in advance!

    I bookmarked it.

  28. Sumit Chaturvedi

    Hi Paul,

    I have below queries regarding script:

    • The script is for Exchange 2010 and up, but doesn’t account for the fact that ServerRole values has changed since 2010. This is why it’s showing Hub Transport as failed, although why it thinks Client Access is good is a bit of puzzle. We’ll either have to remove or alter that part of the script so it’s not showing false errors
    • The script PowerShell Logon section needs to be re-written to work as Automatic Task. How can this be done?
    • The script is showing a lot of Replay Queue errors, I believe these are caused by the Lag Copy databases we have. How to deal with this?

  29. haydar tekir

    Hello,

    nice script btw. However I get the following error when I execute the script:

    Mail flow test: WARNING: Connecting to remote server mail.hisolutions.com failed with the following error message : WinRM cannot
    process the request. The following error occurred while using Kerberos authentication: Cannot find the computer
    mail.hisolutions.com. 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:\org\exchange\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:452 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

    I have a Exchange Server 2016 DAG with two servers. and a standalon server running Exchange 2013 running in the same organization. The OS of the exchange 2016 is Windows server 2016

    Rgds

    Haydar

    1. Nick

      Hey haydar, I had the same problem. However, as per suggestion from Mark before the past, if you comment out

      $url = ….. from (around) line 418

      does this solve your problem?

  30. Fred

    Hi Paul, many thanks for this very useful health check script, just had a quick question regarding the exclusion file.
    I have no issue listed servers that I want to exclude, however I have a challenge listing some databases to exclude, i.e I have some restore DBs which are unmounted and want to exclude them from a couple of servers but listing the database names don’t seem to work.
    Could you advise what is the correct format to allow this to work.

    Thanks, Fred

  31. Yasir Khan

    Paul this script has been very useful as have the other scripts which you have compiled. Thank you very much for the time taken to create this script

  32. Shannon

    Paul, this script is awesome, thank you so much… We have been having issues with our environment and this at least gives a heads up before the users report problems.

  33. shahin

    hi friend,
    but when i run this script , i have error
    Mail flow test: WARNING: Connecting to remote server srv-XX failed with the following error message : The WinRM client cannot proces
    s the request. The WinRM client tried to use Negotiate authentication mechanism, but the destination computer (SRV-XX:80) returned a
    n ‘access denied’ error.
    WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Provide an argument that is not null or emp
    ty, 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:\Users\aslaniadm\Desktop\Test-ExchangeServerHealth.ps1:452 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Finishing

    why this occurred and what can i do ?

  34. DAA3805

    The script fails on the mail flow test with the following … any idea why?

    Mail flow test: WARNING: Connecting to remote server xxx.xxxxxx.com failed with the following error message : WS-Management cannot process the request. The
    operation failed because of an HTTP error. The HTTP error (12152) is: The server returned an invalid or unrecognized response . 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.

  35. Chi

    Hi Paul,

    Good day!

    I was using this script and it works perfectly but after moving my mailbox database from the default path to drive D I kept on getting an error/warning “Could not test service health. ” I don’t want to ruin the script since I am new to exchange. But if I need to, can you please tell me where in the script should I change the path or directory.

    Thank you,
    Chi

  36. Daniel

    Hi, Paul:

    Very useful script thanks a lot.

  37. Arun

    my issue is in exchange server 2016 the default online search limitation is 250…but i need to increase the search limitation to 2000.

  38. metin

    Hi Paul;
    I wanted to add the following commands to the report but failed. Can you help me with this?

    Get-MailboxDatabase -Status | sort name | select name,@{Name=’DB Size (Gb)’;Expression={$_.DatabaseSize.ToGb()}},@{Name=’Available New Mbx Space Gb)’;Expression={$_.AvailableNewMailboxSpace.ToGb()}}

    Thank you for making the report. 🙂

  39. Stephan P

    Good morning Paul,

    thank you for the great script.
    Unfortunately I get 2 different results.
    The problem ist the mail flow test.
    The log says ‘Mail flow status is Erfolgreich’
    The html Check Report says Mail flow test failed. (in red)

    Any solution?

    Regards

    Stephan

  40. Mark F

    Hi Paul, we have been using this script daily to check on our environment. I am currently on Exchange 2016 / 2010 co-existence. I updated Exchange 2016 to CU11 this weekend and now the script is showing null value errors for
    “You cannot call a method on a null-valued expression.
    At D:\Scripts\Test-ExchangeServerHealth2\Test-ExchangeServerHealth.ps1:1575 char:17
    + $DagMemberVer = ($GetExchangeServerResults | Where-Object {$_.Na …”

    This was working fine with Exchange 2016 CU9. The printed report has no names under the server column in the DAG sections and the Exchange 2010 Dags show the “server locator service” Failed on every Exchange 2010 server. I reviewed each Exchange 2010 server using Test-Replicationhealth and the error does not show up there.

    Ideas?

    1. Mark V

      Curious if you ever solved your “no names under the server column” problem … we were a few CU’s behind and just installed CU12 … and are see the same now too. Also seeing blanks for “Preference” related columns … I assume it’s related.

      1. Mark V

        I was running the script from a management server … once I updated that server with CU12 the script started working properly again. Happy to see it working again.

  41. Paul

    Hi Paul

    Great article as always, but just came across an interesting issue in a test environment, when the server name isn’t all in upper case. This resulted in the script being unable to report on activation preferences of the database copies.

    The following line in your script was attempting to perform a case-insensitive comparison between server names, but if they weren’t exactly the same case, it wouldn’t return any results.
    $pref = ($database | Select-Object -ExpandProperty ActivationPreference | Where-Object {$_.Key -ieq $mailboxserver}).Value

    I needed to specify the “Name” property of the “Key” for this to work correctly:
    $pref = ($database | Select-Object -ExpandProperty ActivationPreference | Where-Object {$_.Key.Name -ieq $mailboxserver}).Value

    Cheers

    Another Paul

  42. Séb

    Hi Paul, thanks for this useful script.
    Have you already test it on Exchange 2019 ?
    Same question for the DAG Health check ? 🙂

    Thanks,
    Regards

  43. Ercan Ufuk GARGIN

    Hello Paul,

    I found the solution

    It is “Server Management” and “Remote Management Users” roles.

    Regards

  44. Ercan Ufuk GARGIN

    Hello Paul,
    When we try to run script it gives an error below;

    Mail flow test: WARNING: The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    Fail

    It was working fine but we accidentilly remove running users groups.

    Can you help us to work again?

    Thank you for great script.

    Regards.

  45. Rob

    Terrific script! It has everything I need except disk space. Would that be a feature to add later? I’ve tried to add it myself, but broke many things within.

    Thanks for the awesome work!

  46. jd

    Hi Paul, great script, we have been using this for production use with Exchange 2016 CU9.

    After recently installing CU10, the Server name column under “Database Availability Group ‘DAG’ Member Health” is now coming up empty. All the other boxes still pass

    Do you have any idea why this would stop this working?

    Looking in the code that first row appears different to all the others:

    $htmltablerow += “$($line.”Server”)
    $htmltablerow += (New-DAGMemberHTMLTableCell “ClusterService”)
    $htmltablerow += (New-DAGMemberHTMLTableCell “ReplayService”)

    Thanks

  47. Steve Money

    Fantastic Script!!

    I am having 1 issue however.

    I am currently running a Exchange 2010-2016 co-existence environment. 1 of my Exchange 2016 servers shows a “Unable to Retrieve Uptime” message. All other servers are working fine.

    Any ideas on what is not working?

  48. Guillaume Roucou

    Hi,

    I would like to ignore a specific database but it doen’t work.
    How do I specify database in ignore.txt file ?

    database/server
    or
    database

    I try both but it doen’t work.

    Thx

  49. Michael Wawrzyniak

    For anyone who is running into problems making this script work with Task Scheduler, I got it to work. Initially using the author’s instructions, it did not work. Task Scheduler said that the task completed successfully almost instantly, but the script did not run.

    I’m running this on a Server 2016 / Exchange 2016 CU10 server.

    – Run As: (my domain Exchange Admin account)
    – Run whether user is logged on or not
    – Run with highest privileges
    – Configure for: Windows Server 2016

    – Start a program
    – Program/script: Powershell.exe
    – Add arguments (optional): -ExecutionPolicy Bypass C:\Scripts\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail
    – Start in (optional): blank

    I messed around with a bunch of the settings, but I believe the main issue I was having related to not having the ExecutionPolicy, plus trying to use -command “script path+name+params”. You don’t need any quotes in the “Add arguments” section.

    Hope this helps anyone else who wanted to schedule this awesome script! Thanks again for making it and maintaining it for us!

    1. Asela De Costa

      Thank you so much

  50. Bill Bowling

    Just a note: I have been using this script since it came out. I had 2010 and 2016 exchanges servers. I just finally removed my one exchange 2010 server. Everything went fine. My question is this script is still showing the removed exchange 2010 server in the results. Do I have to wait a day or so after removing DNS, AD, etc. related to the removed server?

    Thanks.
    Bill

  51. Darya

    C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\data\Queue>”C:\Pro
    gram Files (x86)\Log Parser 2.2\logparser.exe” “SELECT data as [Status Code],Cou
    nt(*) as Hits FROM *.log WHERE data LIKE ‘5%’ GROUP BY data ORDER BY Hits DESC”
    -i:CSV -nSkipLines:4 -rtp:-1
    Error: SELECT clause: Syntax Error: unknown field ‘data’

    To see valid fields for the CSV input format type:
    LogParser -h -i:CSV

  52. James Ledgard

    if anyone’s getting the mailflow test failure, check the servers NIC card has Register DNS Ticked (not normally set for a server with static address) as exchange mailflow requires this, you then get a clean bill of health

  53. John

    I finally got Email to work! However, the htmlreport does not generate when running with PowerShell directly or running a scheduled task. I have to run it in C:\Scripts by running .\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail. Any suggestions?

    ###########Define Variables########

    $fromaddress = “ExchangeReport@yourdomain.com”
    $toaddress = “username@yourdomain.com”
    $Subject = “Daily Exchange Server Report – $now”
    $attachment = “C:\scripts\Oakwood Exchange Server Health.html”
    $smtpserver = “smtp.yourdomain.com”

    ####################################

    $message = new-object System.Net.Mail.MailMessage
    $message.From = $fromaddress
    $message.To.Add($toaddress)
    $message.IsBodyHtml = $True
    $message.Subject = $Subject
    $attach = new-object Net.Mail.Attachment($attachment)
    $message.Attachments.Add($attach)
    $message.body = $body
    $smtp = new-object Net.Mail.SmtpClient($smtpserver)
    $smtp.Send($message)

    1. John

      I figured it out.

      I created a batch file and input:

      c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -command C:\Scripts\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

      All working now

      Thanks Paul!!!

  54. Phil Brooks

    Great script! I’ve been using it for years on Exchange 2016. Any tips for getting this to work in Windows Server 2016 task scheduler for Exchange 2016?

    1. Avatar photo
      Paul Cunningham

      I don’t have any WS2016 servers to test it on right now I’m afraid.

  55. John

    Hi All,

    I have other DAG Servers which shows Green and Healthy for DB Copy Suspended DB Copy Failed DB Initializing DB Disconnected DB Log Copy Keeping Up DB Log Replay Keeping Up

    However, I have one Server that shows N/A but the Cluster Service Replay Service Active Manager Tasks RPC Listener TCP Listener Server Locator Service DAG Members UpCluster Network Quorum Group have passed.

    Does anyone know why It’s not checking DB Copy Suspended and etc and outputting N/A?

    Thanks!

    1. Avatar photo
      Paul Cunningham

      Some of the tests are n/a when the mailbox server has no active mailbox database copies on it. Basically the Test-ReplicationHealth cmdlet is what is returning those results, and if it doesn’t return a result for one of the items, the script lists it as “n/a” for “not applicable”.

  56. SANKARASUBRAMAN PARAMESWARAN

    it is not working for exchange 2016.

    This script does not find the DAG health summary for exchange 2016 and IP less DAG

  57. Jon DeSalvatore

    Thanks for this cool script Paul. Appying this to EXC2016 and its working . I set up 2 seperate task schedules for this. One runs at 7am daily and sends a report. Then I have a seperate one that runs every 30 minute and will only send an alert if something is amiss.

    The issue I am having is that I am getting email alerts about the reply queue being 9 or 12. Is there a way tone down the sensitivity of the replay queues so that I would only get notified when its lets say over 100? Thanks!

      1. Jon DeSalvatore

        Can you guide to where?

  58. Jeremy

    Love this script and would like to include a disk space check as well. Probably like most people, we use Volume Mount Points for each DB and LOG directory. Most monitoring tools are not able to check disk space on these, so I using the below in another script.

    Any suggestions?

    $TotalGB = @{Name=”Capacity(GB)”;expression={[math]::round(($_.Capacity/ 1073741824),2)}}
    $FreeGB = @{Name=”FreeSpace(GB)”;expression={[math]::round(($_.FreeSpace / 1073741824),2)}}
    $FreePerc = @{Name=”Free(%)”;expression={[math]::round(((($_.FreeSpace / 1073741824)/($_.Capacity / 1073741824)) * 100),0)}}

    function get-mountpoints {
    $volumes = Get-WmiObject -computer win32_volume | Where-object {$_.DriveLetter -eq $null}
    $volumes | Select SystemName, Label, $TotalGB, $FreeGB, $FreePerc | Format-Table -AutoSize
    }

    #$servers = (Get-Content .\servers.txt)

    #foreach ($server in $servers){
    get-mountpoints
    #}

  59. Andrew

    Hi Paul,

    Getting this error on our production Exchange 2016 servers when running the script

    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 36
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 0
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: [Microsoft.Mapi.MapiExceptionSendAsDenied]: MapiExceptionSendAsDenied: Unable to submit message. (hr=0x80070005, ec=1244)
    Diagnostic context:
    Lid: 40487 EMSMDBMT.EcDoRpcExt2 called [length=46]
    Lid: 56871 EMSMDBMT.EcDoRpcExt2 returned [ec=0x0][length=400][latency=15]
    Lid: 52176 ClientVersion: 15.1.1261.39
    Lid: 50032 ServerVersion: 15.1.1261.39
    Lid: 35180
    Lid: 23226 — ROP Parse Start —
    Lid: 27962 ROP: ropSubmitMessage [50]
    Lid: 17082 ROP Error: 0x4DC
    Lid: 27745
    Lid: 21921 StoreEc: 0x4DC
    Lid: 27962 ROP: ropExtendedError [250]
    Lid: 1494 —- Remote Context Beg —-

    Seems to be related to the issue you mentioned for Exchange 2013 which I know was fixed. running the script from the local Exchange server against the local Exchange server works fine.

    1. Avatar photo
      Paul Cunningham

      Other people have reported the same error, but I can’t reproduce it so I don’t know why it is happening, sorry.

      1. Paul

        I’m getting the same message. I’m running this on an Exchange 2016 server that was hardened using CIS for a US government organization.

  60. Tom

    Hi Paul-

    Where does the script get the Exchange server list itself for the Server Health? I have an old server that has been decommissioned it is still looking for and I cant find where it is. Rather than use the ignore text file, I would like to know where it gets the server list from..

    Thank you! This is a great script, its part of our reporting every day.

    Tom

    1. Avatar photo
      Paul Cunningham

      It uses Get-ExchangeServer to retrieve the list of servers for the org. If you run Get-ExchangeServer and you still see your old server, then your old server was not properly decommissioned.

  61. Fang

    Hi Paul, after running this script & look at the report, most items look good but in DAG Member Health section, both my servers with *FAILED* in Database Availability column. Wondering what does it mean actually?

    Can you provide more guidance to me for further troubleshooting?

    Thanks in advance for your help & looking forward to your reply soon!

    1. Tino

      Ditto, i’m wondering what that means. Great script Paul!

  62. Gary

    Feature Request:

    Is it possible to put a quick error alert in the Subject line? For example, anything that is red just filters up a 1 to the subject of the email or 2 or maybe a “# errors”? Love the script!

    Thanks.
    Gary

  63. Mohsin

    Hi paul,

    i am not getting report on email. I have base platform on windows server 2012 R2. Please suggest. Thank You.

    Regards,
    -Mohsin

  64. Mauro

    Hello Paul,

    Thank you not only for this script, but for all your posts, information and experience you are sharing with us. you’re a time savior.

    I am facing a small problem, when i run the script manually, everything is fine and I receive the email, but when i run it from Task Scheduler, i receive nothing.

    I did the same Action and trigger mentioned above, also checked all the comments and errors but nothing helped me.

    when i run the task i can see in the history that action and task completed:
    – Action completed: Task Scheduler successfully completed task “\Exchange Health Report” , instance “{ID}” , action “powershell.exe” with return code 0.
    -Task Completed: Task Scheduler successfully finished “{ID}” instance of the “\Exchange Health Report” task for user “DOMAIN\administrator”.

    What do you suggest?

    once again, thank you!

  65. Christopher

    It seems to have been a while for a post. I’m recently running the script and kudos on it Paul.

    I want to add to show disk space on server drives

    Can you help with that?

    Regards,
    Christopher

  66. Morten Wiingreen

    Hi Paul,

    I am trying to get the script to run in scheduler on a Windows Server 2016 with Exchange 2016 CU7.
    When using -Log I can see the script gets stuck at “Loading the Exchange Server PowerShell snapin”.

    When I run the script in Powershell ISE it works perfektly.

    Any Idea how to get it up and running on a Windows Server 2016

    Best regards and thank you 🙂

    1. Hilario

      Hi Paul,
      Thanks for the script. We have been using it for a while and its great.
      I am having the same problem as Morten while adding 2016 servers.
      I noticed that “Get-ExchangeServer $server” in the script was not returning the 2016 servers so i tried adding :
      $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri “http:///powershell” -Authentication Kerberos
      Import-PSSession -Session $Session | Out-Null
      But then the “Set-ADServerSettings -ViewEntireForest $true” throws an error

      Any ideas would be really appreciated.
      Thanks

  67. Kevin C.

    Hello Paul. Long term reader, first time “caller”. 😉

    We’ve been using your script for quite a while now big fans – Love it. We just got through updating to CU 19 along with 4.7.1 and coinciding with that the script no longer identifies the environment’s lag copy instances and so warnings are generated for the Replay Queues. We’ve confirmed that the lag copy configuration settings remained in tact. We checked and did not see where CU 19 for Exchange 2013 changed lag copy behavior.

    Any thoughts on what may be occurring?

    Thank you.

    1. Avatar photo
      Paul Cunningham

      Maybe that CU has introduced a new lag copy state that the script isn’t accounting for. I don’t have any 2013 servers in my lab to test though. If you have a look at the parts of the script code that deal with lagged copy status you might be able to work out what’s happening.

      1. Kevin C.

        Thank you for the suggestion Paul.

  68. Chris Smith

    Hey Paul – Love the script. Really awesome work. Problem I’m having is the mailflow test. It completes successfully on some of the servers but not all. Manually doing a “Test-Mailflow -targetmailboxserver ” works just fine & again it works fine on 3 of the 5. We are in a mixed mode of Exchange 2010 & 2016. The 2010 boxes work great, just 2 of the 5 2016’s don’t. Any ideas of where to begin?

    Thanks!!!

      1. Chris Smith

        I do get a “Access is denied” when I run the script in report mode. I looked at the administrators group in computer management & they match on all 5 of the servers. I have checked execution policy & all are set to “remote signed”.

        1. Avatar photo
          Paul Cunningham

          Where is that error appearing? In the report? In the console output?

          1. Chris Smith

            It is appearing in the report/log file.

            Thanks!!!

  69. Nolan

    Just wanted to take the time to say thank you for time and effort in putting this all together. It’s a great resource.

  70. Robert

    Great script Paul!
    Wanted to know what is the format of the ignorelist.txt?

    1. Avatar photo
      Paul Cunningham

      Just a list of names, one per line.

      SERVER1
      SERVER2
      DATABASE1

      etc

  71. Tyson

    Paul,

    Thank you for the script! I’m having issues with the ignorelist.txt file and have searched all of the comments looking for a solution to no avail. When executing the script I receive the following:

    WARNING: The file C:\ExchangeHealth\ignorelist.txt could not be found. No servers, DAGs or databases will be ignored.

    I have verified that the file is, in fact, in that exact location. I thought it might be a permissions issue so for testing I gave “everyone” read/write/modify permissions. Still no dice. Any recommendations?

    Thanks!

  72. Troy

    Report shows everything Green on our Exchange 2010 server.

    On our Exchange 2016 server it shows a Fail for “Client Access Server Role Services”. I looked in the Windows Services list, and I’m not seeing anything in a stopped state, except for “MS Exchange Notifications Broker”, and “MS Exchange Mailbox Replication”.

    Now I’m confused if anything is actually wrong.

    1. Avatar photo
      Paul Cunningham

      Run the Test-ServiceHealth cmdlet, it will show you which services it expects to be running.

      1. Troy

        Thanks. Turned out that it was the Exchange Mailbox Replication service that it was complaining about. Trying to figure out why it won’t start now. At the moment there’s only about 3 people on this new exchange server, and I haven’t noticed any end-user functionality problems with it.

  73. John Bales

    This is exactly what I was looking for. I can’t imagine the time it took to get this to where it is and I think we are ALL very appreciative of this! Thank you for not only creating this script, but also for sharing it as well.

  74. Dilip Sasikumar

    Hi Paul… First of thanks for all your contributions to the Exchange world. You are a life saver to may Exchange admins out there. Coming to my issue. I am running this health report in a mixed 2010 ,2016 environment and only 2010 servers are listed in the html report. If i check the logs , i can see 2016 servers are Tested successfully. Any suggestions?

    1. Dilip Sasikumar

      Paul, ignore my query. I was able to get it working after scheduling Task from the 2016 server instead of running from a 2010 server. Thanks!!

      1. Morten Wiingreen

        Hi Dilip, I am having problems getting scheduled task to run on my Server 2016 / exchange 2016.
        Could you share the settings you use?

  75. Andy B

    Hi Paul – did the test Mailflow command failure on remote servers ever get solved?

    Many Thanks

    A

    1. Mark

      I had the same issue. The mail flow part only works fine if Kerberos is configured correctly as Paul said before. You can also ‘fix’ it by commenting line 420. Put a ‘#’ in front of the line. Then it will fall back on the servername (Line 421-424) instead of the URL wich is configured in the virtualdirectory.

  76. Chetan

    Hi Paul,

    We have Exchange server 2013 environment across 3 sites.
    When we execute script, it gives output for all 3 sites located servers.
    We need to execute for each site individually & report should show report for only that site not for all.

    What changes need to be done in script & where it need to be done ? Please Suggest.

  77. Joseph Agius

    Paul

    I very much like your script, thanks. I am trying to run this script and I get the following warning.

    —————————————————————————————————–
    WARNING: No snap-ins have been registered for Windows PowerShell version 5.
    —————————————————————————————————–

    I am running this script on a Windows 10 Machine that has a PSSession to our exchange server.

    What am I missing here?

    Many thanks

    1. Avatar photo
      Paul Cunningham

      The script needs to be run using the Exchange Management Shell, not a remoting session.

      1. Joseph Agius

        Many thanks! How did I overlook that! Sometimes thinking too hard can be your undoing! Thanks for taking the time to respond

        Joseph

  78. Amaro Maguni

    Ok! Great!
    Thanks

  79. Amaro Maguni

    Hi Paul,

    Great Script! Thanks for sharing and for having your blog that helps a lot newbies like me.
    I am having this error when trying to send mails with the report (The Powershell version is 2.0),
    can you assist!?
    Thanks in advance!

    “PS C:\> .\Test-ExchangeServerHealth.ps1

    cmdlet Test-ExchangeServerHealth.ps1 at command pipeline position 1
    Supply values for the following parameters:
    ReportFile: Exchange_Report_24102017.html
    SendEmail: $True
    C:\Test-ExchangeServerHealth.ps1 : Cannot bind argument to parameter ‘ReportFile’ because it is an empty string.
    At line:1 char:32
    + .\Test-ExchangeServerHealth.ps1 <<<<
    + CategoryInfo : InvalidData: (:) [Test-ExchangeServerHealth.ps1], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Test-ExchangeServerHealth.ps1"

    Best Regards
    Amaro Maguni

    1. Mark

      If you add the parameter -ReportFile you should define a reportfile, something like:

      Test-ExchangeServerHealth.ps1 -ReportFile “HealthReport.html”

      The desciption in the help is:

      .PARAMETER ReportFile
      Allows you to specify a different HTML report file name than the default.

      The paramter is optional, you don’t have to use it.

      1. Amaro Maguni

        Hi Mark,

        I am struggling with the “SendEmail” parameter, not the “Report File”.
        If I don’t use the “Send mail” the script works fine!
        Thanks for the tip, anyway!

        1. Mark

          Ah, the error you gave is:

          ‘Cannot bind argument to parameter ‘ReportFile’ because it is an empty string.’

          When you use the e-mail paramter you probably have to define the -ReportFile parameter i think because this is the description: ‘Sends the HTML report’.

          .PARAMETER ReportFile
          Allows you to specify a different HTML report file name than the default.

          .PARAMETER SendEmail
          Sends the HTML report via email using the SMTP configuration within the script.

          1. Amaro Maguni

            I am running “.\Test-ExchangeServerHealth.ps1” command.
            with this changes in the script, below:

            “[Parameter( Mandatory=$True)]
            [string]$ReportFile=”exchangeserverhealth.html”,

            [Parameter( Mandatory=$True)]
            [switch]$SendEmail,”

          2. Avatar photo
            Paul Cunningham

            Setting the parameters to mandatory means you must use those parameters. So if you’re then running the script without parameters, it will throw an error and not run.

            I suggest you revert the changes you made to the script code itself, and just run the script with the desired parameters.

  80. Andi

    cool script, but can you put the
    Get-ServerComponentState
    in the script?
    thx Andi
    from Germany

  81. misterht

    There is another script by Paul for All Mailboxes in the Organization called Get-MailboxReport.ps1. BTW, if you put in the correct parameters the Test-ExchangeServerHealth works beautifully. Just need to be a little bit savvy about your own site and entries.

  82. Rajeesh

    Hi Paul,

    Thanks for this wonderful script!

    How can i add mailbox count per server or DB in this report? can you guide?

    Thanks!

    Rajeesh

  83. prasant

    Hi Paul,

    Thanks for the script, I have been using your script for a while successfuly. Now I am using your script in new organization where I have second DAG member on offsite connected through 100 mb / for both upstream and downstream connection.
    I do get yellow flag on “quorum group” and “database availability group”. Though, it appears to be failing over on shutdown and does show OK on get-databasecopystatus * or test. I would presume the remote server reporting as “unable to retrieve uptime” and “could not test service health” is because of slow pipe

  84. geots

    Hi Paul,

    is it possible to fix the issue on the script with Mail Flow Test failing on remote Exchange 2016 servers?

    Thanks

  85. misterht

    Sir Paul,
    Have the script been updated with all the little things you mentioned in the comments, lately?
    Thanks.

      1. misterht

        Like DAG Copy Status check and to only email when alerts are detected. Those are old comments and I’m thinking you may already have updated those. Thank you very much for a great script that makes and Exchange Admin’s life easier.

        1. Avatar photo
          Paul Cunningham

          Yes, both those features are in the script. You can download the latest version and try it.

          1. John

            Thanks!

            I have one other thing that is having issues. I am able to generate an HTML report. However,

            #……………………………..
            # Modify these Email Settings
            #……………………………..

            $smtpsettings = @{
            To = “administrator@exchangeserverpro.net”
            From = “exchangeserver@exchangeserverpro.net”
            Subject = “Exchange Server Health Report – $now”
            SmtpServer = “smtp.exchangeserverpro.net”
            }

            Does not seem to work for me. When I use:

            param(
            [string]$to,
            [string]$subject,
            [string]$body
            )

            $smtpServer = removed
            $smtpFrom = removed
            $smtpTo = removed
            $messageSubject = “test”
            $messageBody = “test”

            $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
            $smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)

            I get a test Email. Is there something I’m missing that I am not able to get the report? I am on the highest Server with admin rights.

            .\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

            Seems to generate only the report. Scheduled tasks shows completed but does not generate a report or email.

            Thanks!!!!!!!!

          2. Avatar photo
            Paul Cunningham

            John, run the script in the Exchange Management Shell and look for errors in the output when the mail sends. There’s also a -Log parameter for the script which might capture some useful info.

            You can also look at the protocol logs on the SMTP server you’re using to see if/why it’s rejecting the mail.

  86. Tony

    Hi Paul,

    Just come across your script on one of our servers and am running it against a 3 node Exchange 2013 cluster.

    In the email I am getting 3 ‘Exchange Server Health’ sections each with all three Servers listed which is confusing. Is this normal?

    Thanks
    Tony

    1. Avatar photo
      Paul Cunningham

      No that’s not normal, but without seeing the report and log file there’s not much else I can say.

      1. Tony

        Thanks Paul,
        Ran the report again this morning and it worked as expected. Didn’t have a log file from previous attempts so couldn’t send you one (ran with -log this morning).

  87. Yogesh

    Hi Paul,

    I have run the script, and it’s running well, But I am not getting output on mail.

    Could you please send me the correct script with required change.

  88. Allen

    HI Paul,
    My system environment is in Chinese version, running script error

    Add-Member : Cannot bind argument to parameter ‘Name’ because it is null.
    At D:\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:893 char:75
    + $serverObj | Add-Member NoteProperty -Name <<<< $serverinfoservices -Value $svchealth -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCommand

  89. Allen

    Hi Paul
    Add-Member : 无法将参数绑定到参数“Name”,因为该参数是空值。
    所在位置 D:\Test-ExchangeServerHealth\Test-ExchangeServerHealth12.ps1:893 字符: 75
    + $serverObj | Add-Member NoteProperty -Name <<<< $serverinfoservices -Value $svchealth -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCommand

    1. Allen

      if ($Log) {Write-Logfile “$serverinfoservices status is $svchealth”}
      $serverObj | Add-Member NoteProperty -Name $serverinfoservices -Value $svchealth -Force

  90. Amit

    Hello Paul,

    Did you get a chance to look the test-mailflow error what i pasted in detail, can you suggest what best can be done here.

    1. Avatar photo
      Paul Cunningham

      The error doesn’t occur in my test environment, so there’s not much I can do to troubleshoot it. I suggest you try manually running the Test-Mailflow command and see if that reveals any hints for you.

      1. Mark Bolten

        Paul,

        i receive the same error. Some short investigation tells me this:

        The script does this:
        Connect-ExchangeServer -auto -AllowClobber

        I changed it to connect to ‘Server1’ than i receive a mail flow test failure on ‘Server2’. When i connect to ‘Server2’ i recive a mail flow test failure on ‘Server1’. Not sure wich IP is used to send the e-mail from but it might that it is not possible to send an e-mail between the exchange servers? I will try to invstigate this issue to give some more details.

        1. Mark Bolten

          When i run this manualy, i get ‘Success’ as a result. I run the script from a non exchange server with only the management tools installed.

          $url = “http://Server1/powershell”
          OR
          $url = “http://Server2/powershell”

          $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $url -ErrorAction STOP

          $result = Invoke-Command -Session $session {Test-Mailflow} -ErrorAction STOP

          $e15mailflowresult = $result.TestMailflowResult

          $e15mailflowresult

          —–

          When i run this directly on both exchange servers, i get succes as well.
          Test-Mailflow -TargetMailboxServer Server1
          Test-Mailflow -TargetMailboxServer Server2

          Any clues?

          1. Mark Bolten

            Running the Test-ExchangeServerHealth directly on the Exchange servers generates the same error ‘Mail flow test: [Microsoft.Mapi.MapiExceptionSendAsDenied]: MapiExceptionSendAsDenied: Unable to submit message. (hr=0x80070005, ec=1244)’

  91. aKSHAY bAHIRAM

    hello Paul,
    We have changed the details suggested by you & I have put my email address in the from field. I am not sure whats wrong with the report or whats mistaken from my end but I do not receive output email

    1. Avatar photo
      Paul Cunningham

      Use the -Log parameter to output a log file when the script runs. The log file might have some clues why the SMTP send at the end is not working.

  92. Amit

    Hello Paul,

    While running the script getting the below error during the Test- Mail flow , is any can be done to get rid of this issue and get a successful result.

    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 186
    Server version: Exchange 2013
    Roles: Mailbox, ClientAccess
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 0
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: [Microsoft.Mapi.MapiExceptionSendAsDenied]: MapiExceptionSendAsDenied: Unable to submit message. (hr=0x8
    0070005, ec=1244)
    Diagnostic context:
    Lid: 40487 EMSMDBMT.EcDoRpcExt2 called [length=46]
    Lid: 56871 EMSMDBMT.EcDoRpcExt2 returned [ec=0x0][length=304][latency=296]
    Lid: 52176 ClientVersion: 15.0.1320.4
    Lid: 50032 ServerVersion: 15.0.1320.4
    Lid: 23226 — ROP Parse Start —
    Lid: 27962 ROP: ropSubmitMessage [50]
    Lid: 17082 ROP Error: 0x4DC
    Lid: 27745
    Lid: 21921 StoreEc: 0x4DC
    Lid: 27962 ROP: ropExtendedError [250]
    Lid: 1494 —- Remote Context Beg —-
    Lid: 41788
    Lid: 44092
    Lid: 41232
    Lid: 60208
    Lid: 37136
    Lid: 34608
    Lid: 55056
    Lid: 42768
    Lid: 56112
    Lid: 33016 StoreEc: 0x4DC
    Lid: 63016 dwParam: 0x32
    Lid: 39640 StoreEc: 0x4DC
    Lid: 10786 dwParam: 0x0 Msg: 15.00.1320.000:EXCSRV13PRDN01
    Lid: 1750 —- Remote Context End —-
    Lid: 26849
    Lid: 21817 ROP Failure: 0x4DC
    Lid: 60547 StoreEc: 0x4DC
    Lid: 21966
    Lid: 30158 StoreEc: 0x4DC
    —— Finishing
    Done.

    1. mario

      have you had any success with this?

  93. ajit

    Hello Paul,

    Thank you for the excellent script
    I am adding the list of servers which should be excluded in the health checks in ignorelist.txt

    However it is not working
    The script is modified
    ignorelistfile = “$myDir\ignorelist.txt”

    It is replaced with
    gnorelistfile = “e:\scripts\ignorelist.txt”

  94. David McCarthy

    Yes, running the V1.16, 13/04/2017. We did find recently that our AD replication was slow and causing trouble with our lagged copies but that has been resolved. In about 10-12 days we’ll be patching and rebooting again so that may change the situation. I did sort of fix the Preference column but the rest still eludes me.

    Thanks!

    1. David McCarthy

      Hi Paul, is there a way to check the health of our lagged copies, short of forcing them to play down the logs?

      1. Avatar photo
        Paul Cunningham

        Exchange checks that for you. You can see their health in the Get-MailboxDatabaseCopyStatus output.

  95. David McCarthy

    Hi Paul, your generous postings have helped us many times over the last couple years, thank you! A recent issue I have noticed since we installed CU5 on our E2016 on premise is this health report output has changed for us. It could be our environment but I thought I’d mention it although I am attempting some modifications to the script as an exercise in learning powershell better. Under the health summary section, the Preferences column is empty and the Lagged Queues column shows 0 instead of 1 for us. Likewise under Health Details the Activation Preference has no entries, and under Member Health the Server column is now empty.

    It seems to be having trouble with lagged copies now, but again it may be just us and not the script. It shows as:
    Database Availability Group Health Check Summary
    The following DAG errors and warnings were detected.
    • DB101 – healthy copy/replay queue count is 3 (of 4 )
    • DB102 – healthy copy/replay queue count is 3 (of 4 )
    • DB103 – healthy copy/replay queue count is 3 (of 4 )
    • DB104 – healthy copy/replay queue count is 3 (of 4 )
    etc.

    Thanks again for such a helpful blog!
    Best Regards,
    David

  96. Matt White

    I’m not sure if this has already been commented on in the previous 800+ posts but I was having issue with the script executing via Scheduled Task. I believe it was due to the execution policy on the local machine, even though I have “Run with the highest privileges” checked and running with domain admin/local admin credentials.

    Try running the argument with the following switches:

    -noprofile -executionpolicy bypass -file C:\LocationsOfFileTest-ExchangeServerHealth.ps1 -Log -SendEmail

    Works fine for me now.

    Hope that helps anyone experiencing the same issue.

  97. Jason

    Hi Paul

    Thanks for this useful script

    We were experiencing Event ID 9045 “Service MSExchangeMailboxAssistants. The assistant Junk E-mail Options Assistant stopped processing database DAG Mailbox Database 1 (855a438f-30d4-4615-b074-3e1e7a669935) because the database is in an unhealthy state.” errors every 15 mins – when checking the DAG it appeared to be healthy however and test replication health returned success for both mail nodes. I ran your script and whilst it did error in a couple of places it seemed to test everything ok – the next morning however users were met with a message ‘your administrator has made changes that require you to restart outlook’

    I don’t think the maibox moved between DAG/nodes or anything – have you seen this happen before?

    Many thanks in advance, Jason

    1. Avatar photo
      Paul Cunningham

      Database replication might be healthy but the database itself might have some problems. You should open a support case with Microsoft for advice n that one, or if it’s confined to a single database you could also create a new DB and evacuate that suspect DB and get rid of it.

      The restart message in Outlook is possibly due to a DB failover between DAG notes. If any of your CAS namespaces or other vdir settings are inconsistent then clients might see those types of messages. Run https://exchangeanalyzer.com/ if you want to quickly check for obvious issues.

      1. Jason

        Hi Paul

        Many thanks for taking the time to reply. I’ll check this out

        Regards

        Jason

  98. Preston

    I run this script in both my Exchange 2010 environment and my 2016 environment.

    I am seeing errors in my 2016 environment:
    Starting a command on the remote server failed with the following error message: The I/O operation has been aborted because of either a threat exit or an application request.

    Also:
    The request fro the WIndows Remote Shell with Shell ID *** failed because the shell was not found on the server. Possible causes are: the specified ShellID is inccorect or the shell no longer exists on the server.

  99. chris

    Hello Paul
    we use your script exchange-server-health. A great Code and great tool.
    we use it with -SendEMail -AlertsOnly Parameter.

    Is it posible that change the warning limits, because now we become to many Mail with warnings?
    Example – today:
    yellow Healthy Queues Unhealthy Queues 1
    and
    yellow Replay Queue = 21
    I think thats to small limit für 2 Exchange with 1000 Users

    great tool – thanks to all

  100. Kamal

    Is there is a way to include the following information to the part of the report.
    Mailbox server hosting active copy
    Database Size and whitespace
    Mailbox Count on each database
    Mailbox Average Sizes
    Database and log disk free space
    Last Full Backup
    Mailbox database Queue status
    Mail Queue status on HUB server

  101. Aftab

    Hi Paul,

    is there a way to convert the report to pdf? and then mail it out as an attachment?

    Thanks.

    1. Avatar photo
      Paul Cunningham

      I haven’t looked into it. Perhaps there is some PowerShell modules that can handle that. Sounds like an interesting customization for you to try out, but I won’t be adding it myself.

  102. Aftab Mohammed

    Hi Paul,
    I seem to get the below error but am not sure how I can resolve this:
    Mail flow test: WARNING: Connecting to remote server uk.olayan.net failed with the following error message : WinRM cannot process the
    request. The following error occurred while using Kerberos authentication: Cannot find the computer uk.xxxx.net.
    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:\support\ExchangeServerHealth\Test-ExchangeServerHealth.ps1:452 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

  103. Hans Kristian

    Thanks for a great script Paul,

    Have you considered adding a check for inactive component states?
    I ended up running a modified version of Mr Loeber’s Get-Exchange2013ComponentStateHistory script alongside your health check script since my HLB didnt pick up on the inactive states.

  104. Alex

    Paul,

    Can you implement what Rosario did in future releases?

    – local Drives: Capacity, Used, Free Space

    – Mount Points: our DBs are directly attached via SAN now, so again, MountPoint Name, Capacity, Used, Free Space

    – DB statistics: DB Size, Number of Mailboxes, Mailbox Average Size, WhiteSpace in DB, Date of last FullBackup

    1. Rafal

      Paul,

      Same here, if possible can you please add?

      Especially the DB size can be useful as DAG will only failover if the DB is less than 1TB in Standard edition.

      Thanks for considering Paul.

  105. Csaba Papp

    Hi Paul,
    It is nice and healthful script. Many of the interested information is there. What I would add is: DB backup status (warning if the backup is older than 7 days), certificate expiration (warning if they expired or going to expire in X days), disk space issue (specially useful for LOG partion). Also, it would be nice to be able to exclude one or more counters from the report (adding “#” ..)
    Thank you.

  106. sean daly

    Hi
    ignorelist.txt is being ignored for me, it is stored in the same folder as the PS script
    Any ideas ?

    1. Avatar photo
      Paul Cunningham

      What do you see in the console or in the log when you run the script?

  107. Eric

    What does the result total queue mean? I have 598

    1. Avatar photo
      Paul Cunningham

      I don’t have a column named total queue in my report. Which section are you seeing that in? Are you using the latest script?

      1. Eric

        I should be, script Updated 4/13/2017

        Here’s a part of what I see when I run the powershell script:
        DNS Check: Pass
        Ping Check: Pass
        Uptime: 2717
        Server version: Exchange 2010
        Roles: ClientAccess, HubTrasport
        Client Access Server Role Services: Pass
        Hub Transport Server Role Services: Pass
        Total queue: 601 (This number is in red)

        Am I using the wrong one?

        1. Avatar photo
          Paul Cunningham

          No it just wasn’t clear that you were referring to the console output instead of the HTML report.

          Total queue is the number of messages in your transport queues. You can investigate that further by running the Get-Queue cmdlet.

  108. Patrick Tchuitio

    Paul,
    I just wanted to take a moment to say thanks for your work on this. Just brilliant! Works like a charm. Keep up the great work.

  109. Sukumar Reddy

    Hi Paul,

    I would like to run the health check on Edge Server alone. I have tried removing if from the line
    #Skipping Edge Transports for the general health check, as firewalls usually get
    #in the way. If you want to include them, remove this If.
    if ($IsEdge -ne $true)

    and also tried by changing the value to if ($IsEdge -ne $true) to if ($IsEdge -eq $true) but didn’t work.

    Coud you please help me with it?

    1. Avatar photo
      Paul Cunningham

      I haven’t written any test logic for Edge Transport servers, so I wouldn’t expect that to work at all.

  110. TonyD

    Hi Paul.
    Can anyone help with this issue

    Mail flow test: WARNING: Connecting to remote server mbox-2 failed with the following error message : The WinRM client c
    annot process
    the request. It cannot determine the content type of the HTTP response from the destination computer. The content type
    is absent or invalid. 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:\Scripts\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:450 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

    Thank you

    1. Avatar photo
      Paul Cunningham

      Check whether you can create a PS remote session to that Exchange server manually. Might be something wrong with the WinRM config.

  111. Akash

    Paul, I am getting the error as below:

    —— Checking EXC02
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 105
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 0
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: Connecting to remote server mail.cam.net.in failed with the following error message : WinRM cannot process the request. The following error occurred while using Kerberos authentication: Cannot find the computer mail.cam.net.in. Verify that the computer exists on the network and that the name provided is spelled correctly. For more information, see the abo
    ut_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:\Users\admin\Downloads\Test-ExchangeServerHealth.ps1:450 char:22
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Checking EXC50
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 1231
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 0
    Mailbox databases mounted: Pass
    Mail flow test: No active mailbox databases
    —— Finishing
    Done.

    1. Avatar photo
      Paul Cunningham

      That error occurs when the PowerShell virtual directory has been configure with an alias for the URL.

  112. Kaan

    Mail flow test: *FAILURE*

    Only Exchange Server 1 is giving this error. I am checking queue viewer ;
    Last Error: 421 4.4.2 Connection dropped due to ConnectionReset

    I disabled Windows firewall and psychical firewall for exchange ip address. but problem still is continuing

    Malware agent status disable.

    can you help me ? Thanks.

  113. Mohammad Ajan

    power shell script output to HTM or CSV
    how we can add output method to the script

    1. Avatar photo
      Paul Cunningham

      The script already supports outputting to a HTML file.

      Output to CSV file is not included in the script. The structure of the data is not suitable for CSV format. If you need CSV output, you’ll need to customize the script to meet your requirements.

  114. Alex Graham

    I’ve just tried to run via scheduled task to send an email and no joy – ive even changed to run via the exchange management shell and then does send email but then just the headers and nothing else…

    To save me any time and changing all the code – is there a way we can just make the script to be persistent to just always send the email to the smtp settings?

    1. Avatar photo
      Paul Cunningham

      You can change the code around the Send-MailMessage commands so that it always sends the email, but it doesn’t sound like that will solve your problem. You can also output the report to HTML file to see whether the problem is with the data collection or the sending of the email itself. If the HTML report looks fine, then it’s an SMTP problem of some kind. If the HTML report is broken, then something else is wrong. There’s also the -Log switch which might help you with visibility into what’s going wrong.

      1. Mohammad Ajan

        Mohammad Ajan

        how we can get output of power shell script to HTM,CSV we want to click on this file and give me result in htm,or CSV how we can include htm output
        plese write here the method of output in the script

  115. Sithandiwe

    When I run the script (-sendemail), it does not output the DAG HEALTH SUMMARY and DAG HEALTH DETAILS, it only output Server Health check and DAG health member checks.

    1. Avatar photo
      Paul Cunningham

      Run the script in your Exchange Management Shell with the -Log parameter. Watch for errors on screen, or review the log file to see if there’s any issues. Make sure you haven’t added the DAG name to the ignorelist.txt file.

  116. none

    Version 1.15
    Line 424 references variable $testresult that does not exist anywhere else in the script… ??

  117. ajit

    Sending email.
    Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Supply an argument that i
    s not null or empty and then try the command again.
    At H:\Test-ExchangeServerHealth.ps1:2103 char:20
    + Send-MailMessage <<<< @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF
    8)
    + CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage

  118. ajit

    When script is run it show below error

    Sending email.
    Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Supply an argument that i
    s not null or empty and then try the command again.
    At H:\Test-ExchangeServerHealth.ps1:2103 char:20
    + Send-MailMessage <<<< @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF
    8)
    + CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage

  119. Parag

    While executing script in our environment it fails with below errors.

    [PS] C:\script>.\Test-ExchangeServerHealth.ps1
    Initializing…
    WARNING: The file C:\script\ignorelist.txt could not be found. No servers, DAGs or databases will be ignored.
    —— Checking EXSVR16A
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 359
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 1
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Provide an argu
    ment 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:\script\Test-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Checking EXSVR16B
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 359
    Server version: Exchange 2016
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 4
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Provide an argu
    ment 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:\script\Test-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Finishing
    Done.
    We are using Exchange 2016

    1. Avatar photo
      Paul Cunningham

      See comment above. I’ll try and fix this as it seems to be impacting so many people.

    2. Ron

      We had the same error. It turned out that we had inadvertently changed our Powershell virtual directory URLs to use https and our load balancer name, so this script was failing to create a remote powershell session. We reverted the URLs back to the defaults (http://servername.domain.tld/powershell) and the error is gone.

  120. Joseph Liu

    I am using Exchange 2013 and have 4 mailbox servers in a DAG – three in primary site and one in DR site. I tried running the script in the three mailbox servers in the primary site and notice that the mail flow test always fails only in the server running the script while the mail flow test for other servers are OK. The error is shown below.

    **** Error begins ****
    Mail flow test: WARNING: Connecting to remote server tvm-exdb03 failed with the following error message : The WinRM client cannot process the request. It cannot determine the content type of the HTTP response from the destination computer. The content type is absent or invalid. For more information, see the about_Remote_Troubleshooting Help topic.
    WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Supply 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. Supply a non-null argument and try the command again.
    At C:\work\Test-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    **** Error ends ****

    Please kindly help.

    Exchange: 2013
    Windows: 2012 Standard
    Powershell: 3.0

    BTW, I think this script is great and very useful for doing health check of Exchange environment.

    Thanks and regards,

    Joseph Liu

    1. Avatar photo
      Paul Cunningham

      Seems a lot of people get that error, but I don’t have an immediate solution for you. I will try and fix it, since it seems to be such a widespread problem.

  121. Jeff Levin

    I spoke too quickly. Even though I got the script to run from the task scheduler and send email, the main data line in the report was blank. The log file reports “No DAGs found.”

    So I revised my batch file to include the server parameter:

    powershell.exe -PSConsoleFile “C:\Program Files\Microsoft\Exchange Server\V14\Bin\ExShell.psc1” -command “C:\scripts\Test-ExchangeServerHealth.ps1 -server myexchgsrv.mydomain.local -log -ReportMode -SendEmail”

    But that produces the produces a log file that terminates with the line, “could not find the server myexchgsrv.mydomain.local

    Both versions of the batch file work fine from the command line. Any idea of what could be causing the server to be unfindable when running from task scheduler?

  122. Prasad Jahagirdar

    Hi Paul, Thanks for your script but I am getting below error and mail flow Test is failing on one server “Jet-MBX1” only regularly with script whereas if I Test -mailflow on server manually it shows result as “success” so script is showing False result.
    How can we correct this, Please suggest. My email address is as shown below.

    Prasad.jahagirdar81@gmail.com

    mail flow test: WARNING: Connecting to remote server jet-mbx2 failed with the following error message : The WinRM client
    cannot proces
    the request. It cannot determine the content type of the HTTP response from the destination computer. The content type
    is absent or invalid. For more information, see the about_Remote_Troubleshooting Help topic.
    ARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Provide an argument that is
    ot null or empty, and then try the command again.

    The WinRM client cannot proces the request. It cannot determine the content type of the HTTP response from the destination computer

  123. Padmaraj Vykundam

    Thank you Paul, Great work…

    I would like to schedule this report on daily basis How can i write ? Can you please help on this.

    Thank you

  124. Ketz

    Thank you Paul. great script.

    we have ben running this since few months and since yesterday we are getting error

    Could not test service health. : System.Management.Automation.RemoteException: Couldn’t get information about the Excha
    nge services using Windows Management Instrumentation (WMI) due to error: WMI exception occurred on server Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).

    trying to figure it out but no clue.

      1. Ketan

        Now we sre getting access denied for all servers in the domain.

  125. Phil

    $unhealthyindexes = @($copies | Where-Object { ($_.”Content Index” -ne “Healthy” -and $_.”Content Index” -ne “Disabled” -or $_.”Content Index” -ne “AutoSuspended”) }).Count

    Ignore autosuspended for $unhealthyindexes since those are no unhealthy.. they are autosuspended 🙂

    1. Phil

      -and not -or.. argh! sorry

      $unhealthyindexes = @($copies | Where-Object { ($_.”Content Index” -ne “Healthy” -and $_.”Content Index” -ne “Disabled” -and $_.”Content Index” -ne “AutoSuspended”) }).Count

    2. Aikiox

      I confirm, I also modified the script to ignore the AutoSuspended. I’ve added it to the Git but Paul Cunningham has not yet accepted the Pull. https://github.com/cunninghamp/Test-ExchangeServerHealth.ps1/commit/576d5d41f8e7b32225f079f5df155ca8ef41be6b

      I have added a control of the space of the partitions of the servers as well as the location of the bases. I also added a ratio between the size of the base and the free space of it in order not to save space for nothing (if there is backup) : https://github.com/aikiox/Test-ExchangeServerHealth.ps1/tree/patch-1

  126. Ranjith

    Thanks for such a good Script.
    We were trying to customize it to our requirement so was trying to understand the script, we are not a full time programmer.
    Could you please explain how the following commands works, because these variables were not declared in Param, please help us understand.

    Function New-DAGMemberHTMLTableCell()
    {
    param( $lineitem ) –> What is the value of this, what it does?
    $htmltablecell = $null
    switch ($($line.”$lineitem”)) –> What is $($line.”$lineitem”)? please help me understand?
    {
    $null { $htmltablecell = “n/a” }
    “Passed” { $htmltablecell = “$($line.”$lineitem”)” }
    default { $htmltablecell = “$($line.”$lineitem”)” }
    }
    return $htmltablecell
    }

    Like wise,
    param( $logentry )
    param ( $e15cas )
    param ( $e15cas )
    param ( $e15mailboxserver )
    param ( $e14mailboxserver )
    None of the above are declared in Param command, but still it works, how?

    1. Avatar photo
      Paul Cunningham

      Short answer, variables don’t need to be declared in param. Param is for script/function parameters.

  127. Aikiox

    Hello,
    I made a pull request on the Git to integrate the basic notion laggued with the status “AutoSuspended”. From the CU4, this new status allows to automatically pause the lagged bases to avoid overconsumption of the bandwidth. I opened a ticket at Microsoft to learn more about this status that is not documented. Here is the answer :
    I confirm that the Autosuspend of the passive bases lag is a normal behavior.
    We reproduce it and I have identified the change in the voluntary code.
    I guess the reason could be a gain in terms of CPU.
    In spec it appears that this change was made in order to reduce the consumed bandwidth to index the active database.
    I recommend you to keep it in autosuspend but you have the command if you want to reactivate the index as in CU1.

    Here is the command to disable this status:
    New-SettingOverride -Name DisableSkipLagCopy -Component Search -Section SkipLagCopy -Parameters @(“Enabled=false”) -Reason “Disable SkipLagCopy”
    The parameter is not taken into account dynamically, it is necessary to plan a reboot.
    After restarting, probably a reseed is necessary because the index is not up to date: Update-MailboxDatabaseCopy nomdelabase -CatalogOnly
    We have reproduced and checked on our DAG this procedure successfully to reactivate the index.

    In the Pull Request, I also added the exact version of the Exchange. It’s always nice to know which CU we have on which server.

    I also put the part “Queue” in function to try repeatedly if one is above the threshold. This is to avoid having alerts when we have just received an enormous amount of email at once.

    Romain

  128. Shaik Jahangir

    Hello Paul,

    I’m getting the below error when I run the script, Kindly help on this.

    WARNING: Connecting to remote server failed with the following error message : WinRM cannot
    process the
    request. The following error occurred while using Kerberos authentication: Cannot find the computer . 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:\temp\Test-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommandFail

  129. Kumar

    Hi All

    Can we add oldest log files (Text files) info (Time stamp) with number of days old to the script as another column? Can you please help?

    Thanks

  130. Jeff Levin

    I’m another user who simply cannot get your script to run as a scheduled task. I’ve followed your instructions to the letter and experimented with modifications. Nothing works — the task scheduler just shows it running endlessly. The history hangs on event 110, “task triggered by user.” It stays there until you manually terminate.

    This command works perfectly in an administrative CMD shell:
    powershell.exe -command “C:\scripts\Test-ExchangeServerHealth.ps1 -Server myserver.mydomain.local -ReportMode -SendEmail”

    When you try to set it up as a scheduled task as follows:

    Run whether user is logged in or not
    Do not store password
    Run with highest privileges
    Action: start a program
    Program/script: powershell.exe
    Add arguments: -command “C:\scripts\Test-ExchangeServerHealth.ps1 -Server myexchange.mydomain.local -log -ReportMode -SendEmail”
    Allow task to be run on demand
    Stop the task if it runs longer than 1 hour
    If the running task does not end when requested, force it to stop

    it simply will not run. Can you tell me what I’m doing wrong? I don’t have any problem running a WSUS maintenance script in the same fashion.

    1. Avatar photo
      Paul Cunningham

      Use -Log and see if the log gives you any clues.

      But I would also suggest that “Do not store password” is going to cause a problem.

      1. Jeff Levin

        The log just says
        17 17:03:51 =====================================
        01/26/2017 17:03:51 Exchange Server Health Check
        01/26/2017 17:03:51 01/26/2017 17:03:51
        01/26/2017 17:03:51 =====================================
        01/26/2017 17:03:51 Initializing…
        01/26/2017 17:03:51 Loading the Exchange Server PowerShell snapin

        Is there a way to get task scheduler to use the special Exchange powershell? Or what needs to be added to your script to get the regular powershell to add the Exchange add-in?

        1. Avatar photo
          Paul Cunningham

          If you login with the creds that the scheduled task is running as, does the script work?

          1. Jeff Levin

            Yes, in both instances, it’s the domain administrator. Isn’t the problem one of being able to access the Exchange functionality? All sessions are being run on the Exchange server.

          2. Jeff Levin

            Is there something that needs to be in your profile so that the Exchange Server Powershell snapin is already loaded before the script begins executing?

          3. Avatar photo
            Paul Cunningham

            The script loads what it needs automatically, unless it can’t (e.g. due to permissions). I haven’t been able to repro your issue. I’d suggest creating a new service account and trying a different set of creds for the scheduled task.

          4. Jeff Levin

            Doesn’t the domain administrator have all of the permissions required? What is different (besides screen output) between running it in an administrative command shell and running it with the same account and full permissions from the task scheduler?

            It’s just a standard off-the-shelf Dell server with Server 2012 R2 and Exchange Server 2010 running on it. If you’re curious and would like to examine this mystery firsthand, that can be easily arranged.

          5. Avatar photo
            Paul Cunningham

            Depends what you think the “domain administrator” is. Members of Domain Admins or Administrators don’t get any Exchange admin permissions by default. Exchange has its own permissions model.

            This is your first mention of trying to run it on Exchange 2010. I’ll test on a 2010 box next chance I get. It should work, but I don’t recall the last time I tried it.

          6. Jeff Levin

            Thanks. If it works, please let me know the permissions that the account you use in task scheduler has. Meanwhile, I’ll continue to experiment on my end with permissions and let you know if I find anything.

        2. Jeff Levin

          JSYK: The domain administrator account that I’m using for both the command line and the scheduled task is also a member of the organization management group for the Exchange server.

        3. Avatar photo
          Paul Cunningham

          On an Exchange 2010 server this command is working fine (from cmd.exe and from task scheduler)

          powershell.exe -command “. C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -Log -SendEmail”

          The scheduled task has “Run with highest privileges” ticked per my article above. Without that box being ticked the script stalls on “Loading the Exchange Server PowerShell snapin” in the log file.

          1. Jeff Levin

            Funny … if I modify my path for yours and paste this into an administrative command prompt

            powershell.exe -command “. C:\Scripts\Test-ExchangeServerHealth.ps1 -Log -SendEmail”

            All it does is display what’s between the quotes on the next line. If I remove the quotes and the period, it runs correctly from the command prompt. But as always happens — when I put a working command line into task scheduler with the highest privileges (as always), all I get is a neverending “running.” Could you please cut and paste what you have in the “program/script” and “add arguments” boxes of your working scheduled task?

        4. Avatar photo
          Paul Cunningham

          The program is powershell.exe and the arguments are

          -command “. C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -Log -SendEmail”

          I’ve got Exchange 2010 running on WS2008R2, so if you’re on a different OS maybe there’s a PowerShell version thing that needs a different approach.

          1. Jeff Levin

            Hmmm … this is Exchange 2010 running on WS2012R2. Do you know of anyone successfully scheduling it on a similar platform that you can get the arguments from?

        5. Avatar photo
          Paul Cunningham

          Exchange 2010 isn’t supported to run on WS2012R2, so I don’t think you’ll find many people with that scenario.

          You could install the management tools on another server or workstation and run the scheduled task from there.

          1. Jeff Levin

            But it executes perfectly from the command line, so it should execute in the task scheduler as well. Regardless of the Exchange version, could you give me the entry in the parameters box in the task scheduler for a Server 2012 machine where scheduling works? And does installing the management tools on a server require installing Exchange Server 2010 as well? The only instructions I can find seem to say so. https://www.petri.com/install-exchange-2010-management-tools-windows-8

          2. Avatar photo
            Paul Cunningham

            The scheduled task settings I use are in the blog post above.

            The management tools can be installed on a workstation or server without installing the full Exchange server application itself. The tools are a separate role in setup as that blog you link to shows.

          3. Jeff Levin

            Yes, but those scheduled task settings are for WS2008 — they don’t work in WS2012 either as a scheduled task or as a command line. Do you (or anyone else) have the settings for the script working as a scheduled task in WS2012?

        6. Avatar photo
          Paul Cunningham

          I’ve given you what works for me with Exchange 2013 running on WS2012R2 (it’s in the blog post) and what works for me with Exchange 2010 running on WS2008R2 (in comments above).

          That’s all I’ve got I’m afraid. Looking around on Google there seems to be a variety of ways of “running PS scripts in task scheduler” that might have some version-specific nuances but all I can say is what works for me.

          1. Jeff Levin

            I found a solution:

            powershell.exe -PSConsoleFile “C:\Program Files\Microsoft\Exchange Server\V14\Bin\ExShell.psc1” -command “C:\scripts\Test-ExchangeServerHealth.ps1 -log -ReportMode -SendEmail”

            I put it in a BAT file, and it executes from task scheduler now. The console file makes all the difference.

  131. Michael Hart

    Paul,

    Great Script. VERY helpful. I do have a question that I am sure shows how much of a noob I am in Powershell. I am trying to figure out a way for the report name to automatically update with the date of the day it is run.

    Example: 022617.ESH.html instead of exchangeserverhealth.html

    1. Avatar photo
      Paul Cunningham

      There’s a variable in the script that sets the output file name. Just change that to whatever suits your needs.

  132. Anderson Hinojosa

    Paul consulta en mi reporte que me genera , en la columna UPTime me sale este mensaje: Unable to retrieve uptime y se sombrea de amarillo, esto es normal o a que se debe

  133. Martin Hughes

    Hi Paul, Awesome script, I use it to check the health of Exchange 2010 each mornning. I am experiencing a strange issue. I have 2 sites with 2 mailbox servers in each site, the main site has 3 client access\hub transport servers and the other site has 2 client access\hub transport servers. When I run the script as a scheduled task from the main site the report emails however 1 of the CA\HUB servers has the message “Unable to retrive uptime” for uptime hours & “could not test service health” for CAS, HUB, MB & UM. DNS, Ping & Transport queue pass. This only happens on one of the CAS servers on that subnet but I can run the test-servicehealth manually from the EMS.
    When I run the script from a schedule task from the secondary site 2 of the CAS\HUB servers in the main site have the same problem.
    Really hope you can help with this.
    Cheers
    Martin

  134. ErikL

    Paul, I reviewed the comments for this script spanning the last 4 years. I’m impressed with your on-going support. No problems to report, just wanted to drop a line to commend your efforts.

  135. ChrisH

    Paul,
    I commend you on all of the work and scripts you have for Exchange. I have used your resources countless times.
    I have recently implemented Exchange 2013 coexistence with Exchange 2010. No mailboxes have been moved to 2013 as of yet.
    When I run this script from 2013MB5 , I get three failures on mailboxes.
    Exchange 2010MB1, Exch2010MB2 and Exch2013MB5 – access denied
    12/12/2016 09:50:30 Initializing…
    12/12/2016 09:50:31 Loading the Exchange Server PowerShell snapin
    12/12/2016 09:50:37 Setting scope to entire forest
    12/12/2016 09:50:46 You have specified a single server to check
    12/12/2016 09:50:49 Beginning the server health checks
    12/12/2016 09:50:49 —— Checking Exch2010MB1
    12/12/2016 09:50:50 Checking DNS
    12/12/2016 09:50:51 DNS check passed
    12/12/2016 09:50:51 Checking ping
    12/12/2016 09:50:56 Ping test passed
    12/12/2016 09:50:56 Checking uptime
    12/12/2016 09:50:57 Uptime is 858 hours
    12/12/2016 09:50:57 Server is running Exchange 2010
    12/12/2016 09:50:57 Server roles: Mailbox
    12/12/2016 09:50:57 Checking service health
    12/12/2016 09:51:04 Mailbox Server Role Services status is Pass
    12/12/2016 09:51:04 Checking Mailbox Server
    12/12/2016 09:51:09 Checking public folder database
    12/12/2016 09:51:09 Public folder database status is Pass
    12/12/2016 09:51:09 Checking mailbox databases
    12/12/2016 09:51:09 Mailbox database status is Pass
    12/12/2016 09:51:09 Checking MAPI connectivity
    12/12/2016 09:51:16 MAPI connectivity status is Success
    12/12/2016 09:51:16 Checking mail flow
    12/12/2016 09:51:17 Processing data from remote server Exch2010MB1 failed with the following error message: Access is denied. For more information, see the about_Remote_Troubleshooting Help topic.
    12/12/2016 09:51:17 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.
    12/12/2016 09:51:17 Mail flow status is Fail

    Exch2010MB3 and Exch2010MB4 pass with no errors

    If I run the script from a 2010MB, I get no errors and all tests pass.
    Any suggestions?

    1. Avatar photo
      Paul Cunningham

      The mail flow test tries to do a remoting session to the other servers as a hacky workaround for changes in the Test-MailFlow cmdlet when 2013 was released. It throws errors if the remoting session can’t be established. It’s not a great way of doing it, unfortunately.

  136. Jay

    Is there a specific way to setup the ignore list? No matter what I try, it never ignores the servers or DB’s I put in it. I have each one on a single line, no header, no quotes, but I’ve tried it every other way as well and still the report comes with every server that it shouldn’t be checking.

    I currently have 58 servers, 22 of which are 2010 in coexistance with Exchange 2013. I’m on the final stages of the 2010 before I decommission it so I don’t want these to clutter the report, but for the life of me I can’t get the script to ignore these.

    Any suggestions?

    Thanks!

    1. Jay

      NM, think I figured it out. It was ignoring the servers, but I didn’t put in the DB’s and DAG’s for all of those servers.
      Now I am getting only the 2013 servers as I wanted.

      Cheers!

      Now if I can just figure out how to get the scheduled task to work.

  137. stubbo

    Hello Paul –

    Thanks for the great scripts, we’ve been using the DAG health & backup status reports for several years.

    In case anybody’s wondering about the Kerberos error some correspondents have reported…

    The same thing cropped up in our environment with newly deployed Exchange 2016 servers and the latest version of Test-ExchangeServerHealth.ps1

    Mail flow test: WARNING: Connecting to remote server mail.DOMAIN.COM failed with the following error message : WinRM cannot process the request. The following error occurred while using Kerberos authentication: Cannot find the computer mail.DOMAIN.COM. Verify that the computer exists on the network and that the name provided is spelled correctly…

    During the initial server configuration we had set the virtual directories for Powershell on each Exchange server to use the load-balanced name…

    Set-PowerShellVirtualDirectory “$HostNamePowerShell (Default Web Site)” -InternalUrl “https://mail.DOMAIN.COM/Powershell”

    But this isn’t going to work here, so a crude workaround is to #REM out the IF construct around the line…

    $url = “http://$e15mailboxserver/powershell”

    i.e. forcing the script to use a URL incorporating the Exchange server name each time in the New-PSSession command

    Thanks again

    1. Adrian

      Test-mailflow always failed on mbx server hold passive copy DB. Any idea? Error message is same as what mentioned above.
      “WinRM…”

      1. peefee

        I tried the edit recommended by Stubbo but I’m having the same issue. Exchange 2016 with load balancer…

  138. avi

    Hi Paul,

    Love your script – I am new to powershells and this is wow.
    I follow the comments and having a problem running this scripts from the task scheduler.

    Its status is Running but its stays on like that until I end the task.

    my action is: start a program
    Program/script : C:WindowsSystem32WindowsPowerShellv1.0powershell.exe
    arguments : -ExecutionPolicy Bypass -NonInteractive -Command “& ‘C:PowershellscriptExchangeHealthTest-ExchangeServerHealth.ps1’ -ReportMode -SendEmail”

    If anyone made this work it would be great to know how

  139. Venkat

    Hi Paul,

    Could you help me on my request.

    ” have ran this report in my lab everything is perfect very perfect. but i personally feel if you help me to include Diskspace report that would be really helpful for us to understand the Logs drive space and DB drive space”

  140. Royal Wang

    sorry, it is fixed

  141. Royal Wang

    Hi Paul,

    thx 4 ur script, but i have one small problem. why not send one email ro my mailbox even i edit relative settings for SMTP?

  142. Venkat

    Hi Paul,

    i have ran this report in my lab everything is perfect very perfect. but i personally feel if you help me to include Diskspace report that would be really helpful for us to understand the Logs drive space and DB drive space.

  143. Asem Mahmoud

    Dear Paul ,

    when i try to execute your script its working but with the below error

    Script : The term ‘Script’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or
    if a path was included, verify that the path is correct and try again.
    At C:scriptsTest-ExchangeServerHealth.ps1:1 char:1
    + Script Içerigimiz:
    + ~~~~~~
    + CategoryInfo : ObjectNotFound: (Script:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Initializing…
    Creating a new session for implicit remoting of “Get-ADServerSettings” command…
    The file C:ScriptsExchangeServerHealthignorelist.txt could not be found. No servers will be ignored.

  144. Christ

    Hello Paul,

    Hope you are doing well and thanks for the great work.

    I would like to know the syntax or how to create the ignorelist? when runing this script and get-daghealth also.

    Thanks again

  145. Steve Pasikowski

    Thanks for a great tool Paul.

    Our enviroment has Trend Micro ScanMail installed on the Exchange servers. As a result, there is an unmounted database on each server called “EUQ_ReportDatabase_” that is always in an unmounted status. Since the database is not mounted, it reports as a failure in the section “Exchange Server Health” for the column “MB DBs Mounted”.

    Adding these databases to the ignorelist cleans up the noise about them later in the report, but it appears that the ignorelist is not used in the first part of the report that generates the per-server health. They were also causing the MAPI test to fail but I was able to get around that by tweaking the code to only attempt a MAPI test for mounted databases.

    Any thoughts about incorporating the ignorelist into the earlier part of the script?

    Also, during the MAPI checks it looks like the line
    foreach ($db in $mbdbs)
    should probably be
    foreach ($db in $activedbs)

    1. Avatar photo
      Paul Cunningham

      Seems to be a bug. One of many that’s crept in over the years. I’ll see what I can do, but yeah if you spot fixes like that by all means update your copy of the script. Always happy to have bugs/issues and their fixes reported on Github as well where I don’t lose track of them.

  146. Adrian Jackson

    Hi,
    firstly great script, thank you.
    Recently the emailed reports have come through as horrible looking txt, rather than pretty HTML – I suspect after installing the last lot of MS Critical patches to both server 2012 r2 and server 2008 r2.

    Does anyone have an idea either which one, or what it is and how to fix it please ?

    Thanks.

  147. Ihtesham

    Great work…!!! thanks

  148. Fergus Strachan

    Jesus, Paul you must have the patience of a saint replying to some of these comments! (“Please make it PS1.0 compatible” – my reply would be much less measured. 😉 )

    Let me add my thanks for making this.

  149. MikaelJones

    Excellent script. In one environment I get a lot of “Quota violation” (like on the ping check) and “WARNING: Call cancelled”. Next time I run it it works so it seems pretty random. Any ideas?

      1. MikaelJones

        I suspect not since I run the check against 4 servers. I tried narrowing it down to only run it against 1 server and every time I get:
        —— Checking SERVER01
        DNS Check: Pass
        Ping Check: Pass
        Uptime (hrs): 2563
        Server version: Exchange 2013
        Roles: ClientAccess
        WARNING: Call cancelled
        Client Access Server Role Services : Fail
        —— Finishing

        Running CU12 and 2012 R2. Let me know if there are any manual tests you want me to perform to troubleshoot.

        1. MikaelJones

          Doing a manual Test-Connection SERVER01 works fine.

        2. MikaelJones

          I did a restart of the Exchange server in question and it seems like this solved the problem. I will do the same with the other servers to see if this solves the problem. So maybe the 100+ days uptime is the cause 🙂

  150. Pierre-Yves PAVAGEAU

    Hello,

    Still amazing your script. I have just add a modification a long time ago and just reported it to your last version because we are in 2010/2013 cohabitation now, so I need to run your script on the 2013 server instead of the 2010 like said in your documentation.

    I just wanted to put this modification here. The goal of my modificaiton is to have the script running every 15 min and send an e-mail only if necessary :

    ##### ADDED by Pierre-Yves Pavageau
    ##### This part is added at the line 175 (after the SMTP parameters)
    ##### Script is started every 15 min by a scheduled task
    ##### Every 24h an e-mail is sent just to inform that the script is still working
    ##### If i do not receive this e-mail i check the script or the Scheduled task to see what could be wrong

    $ErrorFile = “$myDirerror.txt” # # I am using a file to write error or OK in it (see below the second part of my modification)
    $ErrorValue = Get-Content $ErrorFile

    $compteurFile = “$myDircompteur.txt” I am using a file to increment a value in it (15min * 96 = 24H)
    [INT]$cptDay = Get-Content $compteurFile
    if($cptDay -eq 96) # (15min * 96 = 24H)
    {
    $cptDay = 1
    $cptDay | Out-File $compteurFile ## Setting back to 1 the value in the file compteur.txt

    $SmtpClient = New-Object system.net.mail.smtpClient
    $SmtpClient.host = $smtpsettings.SmtpServer

    ## Generate the report and email it as a HTML body of an email
    $emailContent = “This e-mail is sent just to confirm that the Script which monitors Exchange functionnality is still working. Next e-mail in 24H.”

    $MailMessage2 = New-Object system.net.mail.mailmessage
    $MailMessage2.from = $smtpsettings.From
    foreach ($smtpsetting in $smtpsettings.To)
    {
    $MailMessage2.To.add($smtpsetting) ## Email recipient
    }
    $MailMessage2.Subject = “[EXCHANGE] MONITORING WORKING FINE” ## Objet du mail
    $MailMessage2.IsBodyHtml = 1
    $MailMessage2.Body = $emailContent
    $SmtpClient.Send($MailMessage2)
    }
    elseif($cptDay -lt 96)
    {
    $cptDay +=1
    $cptDay | Out-File $compteurFile
    }

    ##### ADDED by Pierre-Yves Pavageau
    ##### This part is added at the line 2090
    ##### If no issue is found, then no e-mail is sent
    ##### If no issue if found but we had an issue at the last scan we send an e-mail to inform that is back to normal status
    ##### If issue is found, then an e-mail is sent

    I changed this :
    if ($SendEmail)
    {
    if ($alerts -eq $false -and $AlertsOnly -eq $true)
    {
    #Do not send email message
    Write-Host $string19
    if ($Log) {Write-Logfile $string19}
    }
    else
    {
    #Send email message
    Write-Host $string14
    Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8)
    }
    }

    To this

    if ($SendEmail)
    {
    write-host “We will send an e-mail”
    if ($alerts -eq $false -and $AlertsOnly -eq $true)
    #if ($alerts -eq $false)
    {
    #Do not send email message Except if ErrorValue is set to Error
    Write-Host $string19
    if ($Log) {Write-Logfile $string19}
    write-host “Display the error value $($ErrorValue)”
    if ($ErrorValue -like “Error”)
    {
    Write-host “There is no more errors or warning”
    $SmtpClient = New-Object system.net.mail.smtpClient
    $SmtpClient.host = $smtpsettings.SmtpServer
    ## Generate the report and email it as a HTML body of an email
    $emailContent = “This e-mail is sent just to inform you that the EXCHANGE infrastructure is back in normal status.”
    $MailMessage2 = New-Object system.net.mail.mailmessage
    $MailMessage2.from = $smtpsettings.From
    foreach($smtpsetting in $smtpsettings.To)
    {
    $MailMessage2.To.add($smtpsetting) ## Email recipient
    }
    $MailMessage2.Subject = “[EXCHANGE-MONITORING] BACK IN NORMAL STATE” ## Objet du mail
    $MailMessage2.IsBodyHtml = 1
    $MailMessage2.Body = $emailContent
    $SmtpClient.Send($MailMessage2)

    # Writing OK to error file
    $temp1 = “OK”
    $temp1 | out-file $ErrorFile
    }
    }
    else
    {
    #Send email message
    Write-Host $string14
    Write-host “We found a warning or a fail in the report, so we send the e-mail”
    Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8)
    # Writing Error to error file
    $temp = “error”
    $temp | out-file $ErrorFile
    }
    }

  151. Jeff Cothern

    We have a large environment for a customer that has some other business units that have a separate contract for their Exchange servers that are part of the same Exchange Org. We do not manage or have access to those servers.

    I am looking for the best way to use your script to only report for our servers.

    I have attempted to use the -serverlist switch but it only reports on the servers and not the DAG and database information on those server. Using the ignorelist.txt is a little impractical because its a very long list and new servers don’t necessarily get communicated to us.

    Also we have to run the script multiple times to split up our servers and DAGs just to keep the report to a manageable small size.

    So wanted to see options before I delve into modification of the script.

    1. Pierre-Yves PAVAGEAU

      @Jeff

      If you are in the same Exchange Org, isn’t it possible to do this :
      Get all the servers in the Org,
      Filter the list to keep only the one you have under monitoring
      Add the servers not managed by your self to the ignorelist.txt

      Let me know if it helps ?

  152. MetaFR

    Hello,

    Firstly thanks for the code.
    As localised exchange /powershell are, there are some glitch with french version. (Or french a glitch on it’s own ? 😉

    The mailflow routine return “Réussite” and not “Success” , while it’s OK in the case of a “fail” , because anything different than “Réussite” or “Success” is either and error or a fail.

    so for exchange 2013 french localized modify as is :

    line 1141 :
    if ($e15mailflowresult -eq “Réussite” -or $testmailflowresult -eq $success )

    line 1176 :
    if ($testmailflowresult -eq “Réussite” -or $testmailflowresult -eq $success)

    and then script will return correct value in the report

    1. Avatar photo
      Paul Cunningham

      In the blog post above there’s instructions for how to use the existing variables in the script to handle language issues.

      1. MetaFR

        I agree. I partially did but for $success , I was not sure it needed to be edited or not because of being used to partially localized command return ..so I went ahead only editing smtp.
        then got error for the mailflow.
        So , looking closely on line 1176 and 1141, I found that one (1141) as a -eq test with $success and the other one with -eq “success” -or -eq $success and since I initialy dit not localized $success at all and powershell wont return “success” anyway , that’s why I had a wrong return here.
        but I forgot about that $success declaration of you.
        goldfish mode 🙂
        thank you

  153. Elmer

    Hi Paul, first of all thank you for this script that is useful.

    I would like your comment with the following drawback: I have the Escript in scheduled tasks and run it does not show me the following information:

    Database Information
    Exchange Server Exchange Exchange DB DB (GB) Number of Users

    Backup Exchagne Details
    Database Server Name Last Name Last Full Backup Incremental Backup

    But if I run without the Task Scheduler if you show me the entire report.

    First of all thanks

  154. Mahalakshmi

    Thanks for the script. Its very much helpful for us. Can you please advise how to get only “Database Availability Group Health Details” table on the email, since we have planned to send this report alone to all L1 and L2 support guys and we do not wish to send them all other details.

  155. rino19ny

    almost done then got this:

    Mail flow test: WARNING: Connecting to remote server mb2 failed with the following error message : The WinRM client
    cannot process
    the request. It cannot determine the content type of the HTTP response from the destination computer. The content type
    is absent or invalid. 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.

  156. Jason

    Hi Paul,
    Excellent script.

    I’ve been having problems with it not detecting my lagged copies propery. There are 4x copies that are lagged at 2 days. The script does not report them as a lagged copy and errors against the given DAG copy, as the replay queue is quite high.

    It seems the script is not returning the lagged copies under variable $replaylagcopies
    When I echo the command to the console with the “Where-Object {$_.Value -gt 0}” filter it returns no copies. When I run the command without the filter it returns all copies:

    $database | Select -ExpandProperty ReplayLagTimes

    [DCA-EXCH-MBX01, 00:00:00]
    [DCA-EXCH-MBX02, 00:00:00]
    [DCB-EXCH-MBX03, 00:00:00]
    [ADLHB-EXCH-MBX4, 2.00:00:00]

    Given this it seems the filter is not matching correcty.

    I’m running Exchange 2013 SP1 CU13 (current) on Server 2012 R2.
    I did try this script out in January with CU11 and had the same issue, so I don’t think it’s been caused by a recent CU.

    Would much appreciate your insights.
    Jason

    1. Jason

      Hi Paul / All,
      I solved this after also discovering that it was returning a null value for the activation preference. I noted that Sanju (December 29, 2015 at 4:31 pm) provided a fix for the null preference value above.

      Applying the same logic to the lagged copy checks works. It’s probably a little messy but it works.
      Would like to hear of a ‘correct’ fix!

      Old:
      $replaylagcopies = @($database | Select -ExpandProperty ReplayLagTimes | Where-Object {$_.Value -gt 0})

      New:
      if ($database.AdminDisplayVersion -like “Version 14.*”)
      {
      $replaylagcopies = @($database | Select -ExpandProperty ReplayLagTimes | Where-Object {$_.Value -gt 0})
      }
      else
      {
      $replaylagcopies = $dbcopy.ReplayLagStatus
      }
      #End New commands
      if ($($replaylagcopies) -match “True”)
      {
      [bool]$replaylag = $false
      foreach ($replaylagcopy in $replaylagcopies)
      {
      $tmpstring = “$database is replay lagged on $mailboxserver”
      Write-Verbose $tmpstring
      if ($Log) {Write-Logfile $tmpstring}
      [bool]$replaylag = $true
      }
      }

      1. Adam Borders

        I have seen this issue since at least CU 11 and maybe on CU 10. My fix has always been to update the scripting machine to the same CU as the exchange servers.

  157. Stu Cousins

    Hi Paul,

    Thanks very much for the script. Works really well. We had it running on an Exchange 2010 box fine then and moved it to a box on a different subnet. The script runs fine on the new box and all status data is returned. All apart from it says the “File Share Quorum = Failed” for all of the mailbox servers in the cluster. I ran the Test-ReplicationHealth cmdlet from the new server hosting the script and all comes back green. I’ve checked the firewall rules and nothing appears to be getting blocked. Any ideas please and thanks in advance.

    1. Avatar photo
      Paul Cunningham

      Apart from the different subnet, what is different about the server you’re running it from now?

      1. Stu Cousins

        Thanks for your quick response. The server I’m running it from now is a non-Exchange 2010 server. Thats the only difference really. This new server is on the same subnet as the server hosting the file share quorum so its not a firewall issue.

        I fully appreciate its probably an issue with our environment, but I just found it odd that the 99.9% of the health check is successful and the only thing that fails in the ‘File Share Quorum’ check. I’ve checked permissions from our new server to the Quorum and those seem OK.

        I’d be happy to continue running the script on an Exchange server, but our monitoring reports high ‘RPC Requests Outstanding’ alerts when the report runs and these don’t reduce even after the script runs. To clear this we need to reboot the server.

        1. Avatar photo
          Paul Cunningham

          Basically the script is running (or should be running) Test-ReplicationHealth against each DAG member.

          E.g. if you have DAG members named SERVER1 and SERVER2, the script is running…

          Test-ReplicationHealth -Server SERVER1
          Test-ReplicationHealth -Server SERVER2

          …and including the results in the report.

          Now, if you’re seeing those commands running manually and returning a pass, while the report still shows a fail, that is odd behavior. In which case, run the script with the -Log parameter and send me the log file and HTML report file to feedback at practical365.com and I will take a look at it.

  158. Phani Chennakesavula

    Hi Paul,

    Thanks for the great script.

    I’m running through an issue when sending the report through e-mail.

    ==========================
    VERBOSE: Sending email report
    WARNING: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.1 Client was not authenticated
    ==========================
    All the instances I’m running the script on Exchange server (2013; CAS & MBX roles on same box) itself.

    When I run this script with an account that has “Organization management” permissions it executes well and sends e-mail to both external and internal recipients.

    Here we would like to get this done with a non-admin account with less privileges.

    So, Created a new account with mail box “svc-testhealth”

    Added the account to “View-Only Organization Management” Group

    Added the account to local admin group on all exchange servers.

    It runs successfully on the exchange server and logs the information both on shell as well to file, but when it tries to send a mail it fails with above error.

    Can you help me on this?

    Regards,
    PC

  159. Justin Durlewanger

    Paul,

    Thanks for this script. I’ve been using for some time now in our 2010 environment and its beautiful. I noticed when we moved to 2013 its showing our shadow copy queues in the report. Is there a way to exclude shadow copy queues? This is giving a failure on the server transport queues because the shadow copy queues are above 200.

      1. Justin Durlewanger

        Wow! Thanks for the prompt reply Paul! As always you and your site are an excellent resource for any exchange administrator.
        Keep up the great work!

  160. Sumeet Soni

    Hi Paul,

    I have implemented this script to run for each site in my infra but recently experiencing issues where it takes more than 8 hours for it to complete and show results. Is there a reason that you can share for script to take such a long time?

    Quick info:
    Exchange 2010 only.
    I execute this script from server with HT role.
    I run this using schedule task and configured it to terminate if it runs above 8 hrs.
    Only changes to your script that i use is to check for DAG from the current site.

    1. Sumeet Soni

      Request urgent assistance with this.

      1. Avatar photo
        Paul Cunningham

        Have you tried just running it manually and see where it gets slowed down? Or reverting your changes and try the original script without modifications?

        1. Sumeet Soni

          Yes. Manual run generates results but again it takes lot of time and i observed it gets paused while running around half way but starts again after a pause of and hour plus.

  161. David Shriner

    Thanks for providing this script. It has been really helpful in getting an overall glimpse at my Exchange environment. I have encountered one problem recently after upgrading my Exchange 2013 servers to CU12. When I run the script now I get reported errors that Mail flow has failed on all of each Exchange 2013 server. When I look at the log file I see this:

    05/24/2016 06:02:32 Checking mail flow
    05/24/2016 06:02:32 The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    05/24/2016 06:02:32 Mail flow status is Fail

    The script ran fine before the upgrade to CU12 and I am running it with elevated privileges. I have also updated to the latest version of your script with the same results. Do you have any ideas what could be wrong? Thanks for any help you can provide.

  162. Elmer Ernesto Menendez

    Muchas gracias, fue de gran utilidad tu script

  163. Gothdoll

    Paul,

    I am running this script and while I am not getting any errors – the report comes out but there is an issue Id like to resolve without removing these hybrid servers completely out of the script entirely.

    I have 8 HUBS, 4 are set up to communicate with Exchange Online. That being said, the Test-ServiceHealth will always fail on these, multi-role Hub/CAS servers because the MSEdgeSync Service is not needed.

    Is there any way to avoid this, to cont to work in the script on everything else.

    1. Avatar photo
      Paul Cunningham

      I just start the service (and set it to auto start too). The script doesn’t have the logic to tell whether an Edge Subscription exists or not, it just uses what Test-ServiceHealth considers to be a good/bad result.

  164. james T

    hey Paul, love your site BTW.
    I am trying to run the health check report on my two 2013 exchange servers (both are build 1044.25) and keep running into the error below when attempting to email the report, and it happens on both servers:

    mail flow test: WARNING: Connecting to remote server mail.mydomain.com failed with the following error message : WinRM cannot process the request. The following err
    or occurred while using Kerberos authentication: Cannot find the computer mail.mydomain.com. Verify that the computer exists on the network and that the name provid
    ed 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:WindowsSystem32Test-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

  165. Shahir Thottathil

    Dear Paul,

    Hope you are doing well!.

    While i trying to run the script, its running almost okay, but at the end i am always getting an error as given below,

    You must provide a value for this property.
    + CategoryInfo : NotSpecified: (0:Int32) [Get-MailboxDatabase], DataValidationException
    + FullyQualifiedErrorId : 15FA16A2,Microsoft.Exchange.Management.SystemConfigurationTasks.GetMailboxDatabase

    Please help me in this case.

    Thanks and Regards,
    Shahir

  166. Joe

    in the report its say DB redundancy and availability is n/a, whats the reason for that?

    thanks, great script

    1. Avatar photo
      Paul Cunningham

      Depending on the design of the DAG and where the active DB copies happen to be at the time the script runs, some of those items are not applicable.

      1. Jesse

        We had a failed copy a few days a go and the report showed those fields as *FAILED*. Once we resolved the issue, they went back to saying na. Shouldn’t it report “Passed” instead?

        Thanks

  167. naxin

    Hi,Paul, thanks for the great script. I have a error when run the script.

    —— Checking CAS03
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 824
    Server version: Exchange 2013
    Roles: ClientAccess
    Could not test service health. : System.Management.Automation.RemoteException: Not installed on CAS03.electric.com
    Microsoft Exchange 2007 Server Roles

    Is there something wrong in my server config ? thanks.

    1. naxin

      I have three cas server ( exchange 2013 ) , All of them “Could not test service health” , and show “System.Management.Automation.RemoteException” , look like something about exchange 2007 that I have not in my environment.

    2. naxin

      Sorry , I see the page “Exchange 2013 Test-ServiceHealth Doesn’t Work for Client Access Servers” , that is exactly my situation . Thanks a lot.

      1. Avatar photo
        Paul Cunningham

        Some test cmdlets just break if it’s a CAS-only server. I don’t plan to spend much time trying to fix it, sorry. I am investing time in an entirely new script instead. It’s also recommended to not deploy dedicated CAS, and instead deploy multi-role servers.

  168. SteveB

    Paul, thanks for a great script. Quick question, have you considered modifying this script to check for proper log truncation (or does it already do it and I missed it)? Specifically, our backup software regularly issues VSS log truncation requests to Exchange, however some issue with Exchange prevents the logs from truncating. Over time we get notified when disk space runs low, but this script seems like a natural place to check for log file age/truncation.

  169. Lanray

    Hi Paul, Great work.
    This part of the script executes fine for every server in my environment except for one 🙂
    It runs fine on that server only when I replace $e15mailboxserver with its FQDN.

    i.e:
    $url = “http://hostname/powershell” – works for every server except one
    $url = “http://hostname.domain.com/powershell” – Works for the recalcitrant server

    ########################################################################
    if ($url -eq $null)
    {
    $url = “http://$e15mailboxserver/powershell”
    }

    try
    {
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $url -ErrorAction STOP
    }
    ########################################################################

    Any suggestions???
    Thanks!

  170. Aerrow

    Made a few changes on the script. As this is a health checkup, added few tables related the status of the database. But couldn’t find anywhere to upload to you guys to verify.

    1. Avatar photo
      Paul Cunningham

      Github (link in the article) is the best place to submit specific feedback.

  171. Joe Zapata

    Hi Paul,

    Thanks for sharing such a wonderful script. One thing I noticed is that the “Client Access Server Role Services” and the “Hub Transport Server Role Services” are shown as fail (RED) on the email that’s generated. The “Transport Queue” is shown as “Unknown” (Yellow) whenever the script runs from a daily scheduled task on one of my CAS Array member. Everything else is GREEN. I’m using Exchange 2010 SP3 in a CAS Array (2 servers with CAS, HT roles) and a DAG (2 Servers with Mailbox Server roles ) environment.

    Please see below for the Task parameters:

    Program/Script: C:WindowsSystem32WindowsPowerShellv1.0powershell.exe
    Arguments: -ExecutionPolicy Bypass -NonInteractive -Command “& ‘C:TempPSTest-ExchangeServerHealth.ps1’ -ReportMode -SendEMail”

    However, if I run this script below from a PowerShell session on the same CAS array member where I have the task scheduled, the generated email shows all green.
    Test-ExchangeServerHealth.ps1 -ReportMode -SendEMail

    Any reason for this behavior?

    Thanks in advance,

    Joe Zapata

  172. Mike Nadelman

    I was able to create this batch file to run either on demand or using task manager. I works as a batch file but need to add the -sendemail parameter and not sure how to do it. Also need some help to run this as a scheduled task.

    @ECHO OFF
    SET ThisScriptsDirectory=%~dp0
    SET PowerShellScriptPath=%ThisScriptsDirectory%test-exchangeserverhealth.ps1
    PowerShell -NoProfile -ExecutionPolicy Bypass -Command “& ‘%PowerShellScriptPath%'”;

  173. Mike Nadelman

    I was able to create this batch file to run either on demand or using task manager. I works as a batch file but need to add the -sendemail parameter and not sure how to do it. Also need some help to run this as a scheduled task.

  174. martin b

    i have been using this script on my enviroment of EX2010, but now, im tring to use it on the new Exchange 2013 env. all the test are OK, but i never recive the email report… i have allready configured the smtp settings, and are OK. I try to use sendmail and its working too.

    any ideA?

  175. Aleem Ijaz Janjua

    Thanks for the script Paul.

    I’m facing issue in scheduling this script from the task scheduler. I get the wrong report in which the “Up time hrs comes with “Unable to retrieve up time ” and Client Access Server Roles Services “fail”. But when i run this script through windows power shell the report comes perfectly, without any issues.

    I used the same arguments which you have mentioned in your comment earlier.

    can you please tell me how can i get the correct report through task scheduler.

  176. DeSteeph

    Hi Paul,

    This script and none of my other reporting scripts are working anymore since we have applied the Microsoft patches from January 2016. It basically comes down to the part where “get-mailboxdatabase -status” loads the list of servers from memory but that fails (at least.. that is what I suspect). It gives me the output: “you must provide a value for this property”.
    I am running Exchange 2010 SP3 RU11 on W2008R2 SP1
    Did you or any one else run in to this problem?

  177. Dwight

    The script works great when running from my Exchange 2013 servers, but ran into some fields missing from the report when running the script on a non-Exchange (but tools installed) host.

    For the activation preference data that was missing from the report, I followed this comment for the fix: https://www.practical365.com/powershell-script-exchange-server-health-check-report/#comment-197858

    The other item missing from the report were the server names from the ‘Database Availability Group Member Health’ section.

    This was due to the variable $dagmember.names not providing the same value as it did when the script ran directly on an Exchange server. To fix that issue, I ended up just using the $dagmember variable directly.

  178. prasant

    Please ignore the above post. I was not using the -ReportMode parameter. It is now giving me error with gmail authentication which I should be able to fix by disabling dual app verification

  179. prasant

    Hi Paul,

    My issue has been resolved after starting services on passive server. However, when run the script I only get the report on powershell and do not see HTML or email.
    I already modified email parameter and authentication to gmail. I do not get error with script but runs report only on pshell

  180. prasant

    Thanks for your response Paul. I will try -log and send you the log. Friday night I exported and imported certificate from active server and change all CAS, we, autodiscover, activesync services to same FQDN as active server. I did not create second host A on public DNS with different public address and NAT on firewall yet. First I wanted to test internal communication before making changes to my firewall and public DNS.
    I shut down the active server to see the communication from internal Outlook client and it changed to disconnected, until I rebooted the active server and rebooted passive following that. So, I got a feeling there is still issue with mal flow services, outlook anywhere proxy on passive as database replication health is good

  181. Andy

    Excellent script, Paul. Thanks a bunch for writing and maintaining it for the community. I encountered some of the same issues as others noted above, and have come up with the following resolutions for them:

    Server name is blank in DAG member health table:
    change line 1530 to
    $memberObj | Add-Member NoteProperty -Name “Server” -Value $($dagmember.Name)
    – the ‘$dagmember’ variable is just the string, there’s no ‘name’ attribute

    change line 1532 to the following to also fix the verbose logging
    $tmpstring = “—- Checking replication health for $($dagmember.Name)”

    Exchange 2010 DAG health table shows only ‘n/a’:
    change line 467 to
    $e14replicationhealth = Invoke-Command -Session $session -Args $e14mailboxserver {Test-ReplicationHealth $args[0]} -ErrorAction STOP
    – the function is called with ‘$dagmember’ as the argument; related to the $dagmember issue above

    Running in Remote PowerShell:
    If you have an active Remote Powershell session to an Exchange 2013 server, commenting out lines 503-521 will allow it to work flawlessly. This just removes the check for the local snap-in.

    Thanks again for all your work!
    Andy

    1. Andy

      copy/paste fail… Sorry all. here’s the fixed lines 1530 and 5132

      1530: $memberObj | Add-Member NoteProperty -Name “Server” -Value $dagmember
      1532: $tmpstring = “—- Checking replication health for $dagmember”

      Andy

  182. Navneet

    i am getting below error while running this script

    WARNING: No snap-ins have been registered for Windows PowerShell version 4.

    i am using Remote powershell.. version is 4 and i have first connected with exchange organization..
    my all exchange commands are running fine.. excerpt this script

    1. Avatar photo
      Paul Cunningham

      Install the Exchange management shell on the server/workstation you want to run the script from. I haven’t tested it in remote powershell (due to the way the script was originally written) and don’t have any plans to fix this version for remote powershell, but a future version might support remoting.

  183. Carlos Rotver

    Hello Paul, thanks for this script!!

    I have a question: We just added a new mailbox server to a 3rd. DAG we have. All seems to work fine but:

    – Mail Flow Test appears as “Fail” in 3 MBX servers out of 13 servers. We are running the script from a CAS.

    – On the DAG Tests, on the 3rd. DAG, The folloging fields appear as “n/a” for the new mailbox server: DB Copy Suspended, DB Initializing, DB Disconnected, DB Log Copy Keeping Up, DB Log Reply Keeping UP.

    Any idea what this could be?

    Kind Regards,

    1. Avatar photo
      Paul Cunningham

      The “n/a” aren’t a concern because some tests are not applicable if the DAG member isn’t hosting any active database copies at the time.

      For the mail flow test, run the script with -Log and email the log to me, paul [at] this domain.

      1. Carlos Rotver

        Excellent! I will send you the log. Thanks from Mexico!

  184. prasant

    I get this warning, is it normal?-

    ARNING: The file C:certignorelist.txt could not be found. No servers, DAGs or databases will be ignored.
    —— Checking EXC-DAG
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 87
    Server version: Exchange 2013
    Roles: Mailbox, ClientAccess
    Mailbox Server Role Services: Fail
    Client Access Server Role Services: Fail
    Unified Messaging Server Role Services: Fail
    Hub Transport Server Role Services: Fail
    Total Queue: 1
    Mailbox databases mounted: Pass
    Mail flow test: No active mailbox databases
    —— Checking FAB-EXCH13
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 186
    Server version: Exchange 2013
    Roles: Mailbox, ClientAccess
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 2
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: Success
    WARNING: Windows Failover Clustering encountered a transient error. Trying the operation again may be successful. Error: ‘IsNodeClustered’.
    —— Finishing

  185. Ephibob

    Can you help me with a health check script for application servers in Linux SUSE environment? Kindly drop the link here please

  186. Mohamed Elsayed

    I have this error while trying to execute this PS
    I have Exchange 2010 SP1
    Pls Help

    PS C:ScriptsExchangeServerHealth> .Test-ExchangeServerHealth1.ps1
    The ‘<' operator is reserved for future use.
    At C:ScriptsExchangeServerHealthTest-ExchangeServerHealth1.ps1:112 char:13
    + <!– < <<< –>
    + CategoryInfo : ParserError: (<:OperatorToken) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

  187. Gabriel

    Paul,

    This script is great! I have one small issue that I can’t figure out. The Server field for the Database Availability Group member health shows up as blank. All the other fields in that table are fine, just no entries for the Server column. Any ideas?

    1. Avatar photo
      Paul Cunningham

      Generate a log file for the script (use the -Log switch) and send it to me at paul (at) this domain, and I’ll take a look.

  188. Paul Sheath

    Hi,

    I am trying to run this script and get the following error:

    â?” $OS.ConvertToDateTime($OS.LastBootUpTime)
    [int]$uptime = ” : Unexpected token ‘â?” $OS.ConvertToDateTime($OS.LastBootUpTime)
    [int]$uptime = “‘ in expression or statement.
    + CategoryInfo : ParserError: (â?” $OS.Convert…int]$uptime = “:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    Can someone please advise what I am doing wrong here please.

    Thanks

    Paul

    1. Avatar photo
      Paul Cunningham

      Have you modified the script? I’m not sure where the “â” character in your error is coming from.

    2. 0livier

      Hi Paul,

      Same error here when i took the script from Script Center. No problem if you take it frome Github.

      0livier.

      1. Avatar photo
        Paul Cunningham

        Still works okay for me when I download a fresh copy, but perhaps there’s something wrong in the script center somewhere. I’ll make a note to refresh the copy hosted there.

    3. Daniel B

      Copy script into ISE and resave it. I got the same error saving it from Notepad++

  189. Stephane Gagne

    Hi Paul,

    Do you think it would be possible, for the mail flow test, to target a specific mailbox? (e.g. administrator..)

    I’ve been struggling with antispam and cannot whitelist the “systemmailbox….” email address.

    Thanks.

  190. Sanju

    Just for the record if anyone wants to send it to multiple recipient and not a DL I modified it as below to make it work,

    $smtpsettings = @{
    To = “Recipient 1 “, “Recipient 2 “, “Recipient 3 ”
    From = “reporting@xx.com”
    Subject = “$reportemailsubject – $now”
    SmtpServer = “smtp@xx.com”
    }

    1. Sanju

      Dear Paul,

      Just to update on this. I fixed the Activation Preference and Server names for Replication Test by using the below.

      if ($database.AdminDisplayVersion -like “Version 14.*”)
      {
      $pref = ($database | Select-Object -ExpandProperty ActivationPreference | Where-Object {$_.Key -eq $mailboxserver}).Value
      }
      else
      {
      $pref = $dbcopy.ActivationPreference
      }
      This worked out and the report is having the correct output.

      I am also figuring if when using the Alerts Only Switch can we send the message with the error. Suppose the Queue is high we say the queue is high which is ok but if we can mention the current value that would be amazing… I will update if i can make this happen.

      Thanks again

      1. Sanju

        Just used the value with the queue output and worked flawlessly, Now the Alerts have the numbe rof queue as well..

  191. Sanju

    I have been using all the versions when it started back in the days of this script. However I have a challenge now. My client loves this report. But he wants me to take away the email part which I can do and host the HTML as a dashboard and refresh every 20 minutes from the server. Is it something possible to do. Maybe creating an IIS site or something. I am still thinking aout this and thought would ask the experts here.

    1. Avatar photo
      Paul Cunningham

      Try using the -ReportFile parameter to output the HTML file to a folder that is configured as an IIS virtual directory.

      1. Sanju

        Kewl Thanks. One other thing. When Using the parameter -Alerts only is it possible not to have the complete HTML and just send the alerts found. Also what if I don’t want this as an attachment and need it in the body of the email.

        Thanks again for the help. This script is marvelous and a life saver for Admins like us…

        1. Sanju

          Also I noticed on the Activation Preference Table the values are empty. Any thoughts on that.

          1. Sanju

            Dear Paul,

            For me all looks good now…accept no server name in the Replication tests and Activation preference table is blank. I customized the script a bit for the Alerts Only to send the Server Summary and Dag Summary 🙂 Works like a charm.

            Any ideas why the activation preference and server names on replication tests are blank…

  192. Jack

    Important question mailflow test is external or internal

  193. sotomayor

    Hi!

    I executed .ps1 in powershell success and I receive mail correctly.
    I configured scheduled task and I receive mail void.
    The log shown:
    =====================================
    Exchange Server Health Check

    =====================================
    Initializing…
    Loading the Exchange Server PowerShell snapin
    Setting scope to entire forest
    The file C:Scriptsignorelist.txt could not be found. No servers, DAGs or databases will be ignored.
    Retrieving server list
    Removing servers in ignorelist from server list
    Servers to check:
    Beginning the server health checks
    Beginning the DAG health checks
    0 DAGs found
    0 DAGs will be checked
    0 DAGs to check:
    0 No DAGs found

    This is surprise! Do you know case? How I can fix it?
    Thanks in advance

    1. Avatar photo
      Paul Cunningham

      Have you followed the suggestions in the article about the scheduled task settings?

  194. Claudiu Gheorghe

    Hello Paul,

    The latest script is ran from the exchange server which is only CAS and Mbox, dc is on the same vlan. I am able to create “New-PSSession” as you can see below. From what i can gather i see that the script is trying to create a “remote” session to the local exchange server? I also tried it from a diff server on the same vlan and i was able to open a new ps session as admin without get-credential
    Can you give me any hints?

    [PS] C:Usersadministrator.RACKALLEYDesktop>New-PSSession

    Id Name ComputerName State ConfigurationName Availability
    — —- ———— —– —————– ————
    9 Session9 localhost Opened Microsoft.PowerShell Available

    [PS] C:Usersadministrator.RACKALLEYDesktop>Enable-PSRemoting

    WinRM Quick Configuration
    Running command “Set-WSManQuickConfig” to enable remote management of this computer by using the Windows Remote
    Management (WinRM) service.
    This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service startup type to Automatic
    3. Creating a listener to accept requests on any IP address
    4. Enabling Windows Firewall inbound rule exceptions for WS-Management traffic (for http only).

    Do you want to continue?
    [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”): A
    WinRM is already set up to receive requests on this computer.
    WinRM is already set up for remote management on this computer.

    Confirm
    Are you sure you want to perform this action?
    Performing the operation “Set-PSSessionConfiguration” on target “Name: microsoft.powershell SDDL:
    O:NSG:BAD:P(A;;GA;;;S-1-5-21-4179456325-3254648906-924085538-500)(A;;GA;;;BA)(A;;GA;;;RM)(A;;GAGR;;;S-1-5-21-4179456325
    -3254648906-924085538-1162)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This lets selected users remotely run Windows
    PowerShell commands on this computer.”.
    [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”): A
    [PS] C:Usersadministrator.RACKALLEYDesktop>.Test-ExchangeServerHealth.ps1
    Initializing…
    WARNING: The file C:Usersadministrator.RACKALLEYDesktopignorelist.txt could not be found. No servers, DAGs or
    databases will be ignored.
    —— Checking MAIL
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 1
    Server version: Exchange 2013
    Roles: Mailbox, ClientAccess
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 0
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: Connecting to remote server “mail-server” failed with the following error message : Access
    is denied. 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:Usersadministrator.RACKALLEYDesktopTest-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Finishing
    Done.
    [PS] C:Usersadministrator.RACKALLEYDesktop>

    1. Claudiu Gheorghe

      I figured it out,

      The internal URL for Powershell was set to HTTPS, once i change it to HTTP in ECP>Servers>Virtual Directories>PowerShell (Default Website)>Edit>Internal URL: to http://FQDN/powershell, it succeeded in sending the report to my email with this command:

      .Test-ExchangeServerHealth.ps1 -server MAIL -Verbose -reportmode $true -sendemail $true

      Credits go to Paul Cunningham for the above command.

  195. Reynaldo Ruiz Flores

    Error running the script

    Mail flow test: WARNING: Connecting to remote server exchange13.mah.com.mx failed with the following error message : The WinRM client cannot process the request. It canno
    t determine the content type of the HTTP response from the destination computer. The content type is absent or invalid. For more information, see the about_Remote_Trouble
    shooting 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:Usersadministrator.MAHDesktopTest-ExchangeServerHealth.ps1:426 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    1. chris hall

      I have same issue did you resolve

  196. Mukhan

    Hi,

    All of our MS Exchange Users are unable to search from OWA, error: The action couldn’t be completed, Please try again.

    is there any script to find out what is wrong on our Exchange server, Please share.

  197. Glen

    When the database is mounted on server01, the following error message is generated below.
    But, when I failover the database from server 01 to server02 and run the script, there is no issues with the reporting. What would cause the error below? It was confirmed by running the test-exchangeservices that the WinRM service was in a running state on server01.

    Mail flow test: WARNING: Connecting to remote server “server01” failed with the following error message : The WinRM client received an HTTP bad request status (400), but the remote service did not include any other information about the cause of the failure. 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:SCRIPTSServer_HealthTest-ExchangeServerHealth.ps1:425 char:19

    + Remove-PSSession $session.Id

    + ~~~~~~~~~~~

    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

  198. Mukhan

    Hi Paul,

    I want to run this script in my environment to make my life easier, we have a very simple scenario;

    Server 1: Hub and CAS roles installed
    Server 2: Mailbox role installed

    Please let me know what changes should i make as per my scenario and how to run this script, its a bit stupid to ask such things but I am quite new to scripting.

    Thanks in advance.

    1. Mukhan

      I have MS Exchange 2010 SP3

      1. Avatar photo
        Paul Cunningham

        You should only need to change the SMTP settings in the script. Run the script from the Exchange Management Shell to get started. The link to Github in the article has more help info if you need it.

  199. Suraj

    Thanks for script….it works great !!!!!

  200. Paul

    Hi Paul,

    great script and one I use a lot. Just put it into one of the DAG’s I look after and all is coming back healthy… most of the time. However one of the public folder DB’s which is on our DR site keeps coming back as “Public Folder database not mounted. ” However in the same report I get the PFDB as mounted and healthy. Any time I jump onto the server and manually run the script ( it is on a schedule ) it is mounted and healthy. Server has lots of free resource and event logs are clean with no errors. I can only assume the script is timing out or not getting a correct response. But not all the time. Any ideas what I can look for?

    Thanks

    Paul

    1. Avatar photo
      Paul Cunningham

      Send me a sample report as well as the log file that the script produces to paul at exchangeserverpro dot com and I’ll have a look at it.

  201. Kapil K

    Awesome script, Thanks for sharing Paul.

    Require one more help, please let me know if there is any script for below mentioned powershell cmds which can provide the output of these cmds in single file or mail,

    1) Get-MailboxDatabase -Status | ft name,last* -auto
    2) Get-MailboxDatabaseCopyStatus -Server mbx1
    3) Get-MailboxDatabaseCopyStatus -Server mbx2
    4) Get-TransportService | Get-Queue
    5) Test-ReplicationHealth -Identity mbx1 | ft
    6) Test-ReplicationHealth -Identity mbx2 | ft
    7) Test-MapiConnectivity -Server mbx1
    8) Test-MapiConnectivity -Server mbx2
    9) Test-Mailflow -Identity MBX1
    10) Test-Mailflow -Identity MBX2

    1. Avatar photo
      Paul Cunningham

      A PowerShell script is basically just a series of commands. If you already know the commands you want to run, putting them in a script is a very simple step from there. If you’re new to PowerShell scripting then it will be a good learning exercise for you.

  202. Chris

    Paul, thank you so much for your work!! We have exchange 2013 SP1 2 member DAG on server 2012 R2. I can not get this script to either make the report or send an email using scheduled task. The script does send email when run from powershell with the -sendemail switch/option. I looked through the event logs to see if i could see any error but did not see anything related to the script. I have the exact same settings in the scheduled task as you shared in the article above.

    Run whether user is logged on or not
    Run with highest privileges
    Action: Start a program
    Program: powershell.exe
    Arguments: -command “C:ScriptsTest-ExchangeServerHealth.ps1 -Log -SendEmail”

    I have removed the quotes at the end of the arguments to look like this:
    Arguments: -command “C:ScriptsTest-ExchangeServerHealth.ps1″ -Log -SendEmail
    and i have entered the full path in the program line:
    Program:C:WindowsSystem32WindowsPowerShellpowershell.exe

    This task is at the root level of the task scheduler. Not sure what else to try not knowing any error(s). Any ideas?

    1. Avatar photo
      Paul Cunningham

      Put the powershell.exe command line you’re trying to run in Task Scheduler into a .bat or just run it from a cmd.exe, see if you get any different errors. Make sure you’re running the .bat or cmd.exe with the credentials you’re trying to run the scheduled task with too.

      1. Chris

        Thanks for those instructions! Turns out, it did not like the quotes (“) in the command. Removed those and its working like a champ. Thank you again Paul!

  203. Jack Chuong

    Hi Paul,
    Thank you for your script.
    On my Exchange 2013 (Windows 2008 OS) server when I ran script as domain admin at Exchange Power Shell successfully
    cd D:Scripts
    .Test-ExchangeServerHealth.ps1 -SendEmail ==> I received report html email.
    But when I make schedule task for script (as domain admin too) :
    Program : C:WindowsSystem32WindowsPowerShellv1.0powershell.exe
    Arguments : -command “D:ScriptsTest-ExchangeServerHealth.ps1 -SendEmail”
    It didn’t work, the task completed return code 0 but I didn’t receive any email.

    1. Jack Chuong

      I fixed it by select “run with highest privileges” at task setting.

  204. Randall

    Hi Paul

    very useful report however notice database availability and redundancy is showing n/a the rest is passed

  205. HerbZ

    Hey Paul,

    Major fan of your work.!

    Tell, me, where is the output of the HTML content churned out to prior to invoking the SENDMAIL feature?

    PLEASE, SPEAK!

    HerbZ

    1. randall

      is actually at the C root

  206. Matt

    Hi Paul,

    Great script, it does exactly what it says on the tin!

    One question though, is it possible to have the report emailed to more than one address?

    I’ve tried separating different email addresses by space, comma and semi-colon but none seem to work.

    Any thoughts?

    Cheers

    Matt

    1. John

      I’m looking to do the same thing and wondered if Paul has any suggestions?

  207. John

    mail report show mail flow test failed.,

    using .test-exchangeserverhealth.ps1 -server servername
    mail flow test : success.

    i ‘m using V1.14, 21/5/2015

    no idea.

  208. Sanat

    Hi Paul,

    Thank you for the script, its a real great help. However, I was hoping to get a more detailed list of the below commands appended into the script:
    Get-TransportService | Get-Queue | Sort MessageCount – To view a detailed summary of all the queues
    Also if I can pull up Individual Disk Spaces on all the servers with a summary of Free Space, Total Space and Space Consumed
    Last but not the least, a detailed summary of the Mailbox Databases and the size and whitespace in case.

  209. Raj

    I am planning to check the service health of specific DAG servers and its respective CAS and HUB, if I have to create ignore list it will be more in number. Can you please modify script such that I can specify the server list rather than specifying ignore list ?

    1. Avatar photo
      Paul Cunningham

      No. But the script is free for you to take it and customize it any way you like for your own specific needs.

  210. Manfred Paleit

    for a simple sort of Servers …

    #Begin the health checks
    $exchangeservers = $exchangeservers | SORT

    foreach ($server in $exchangeservers) ….

  211. Niclas Johansson

    I get a error message on line 2096:

    Send-MailMessage : Unable to connect to the remote server
    At C:ScriptsExchangeServerHealthtest-exchangeserverhealth.ps1:2096 char:4
    + Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([Syst …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
    ion
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

    Im running this on a Windows Server 2008 R2 with Exchange 2013.

    1. Niclas Johansson

      Instead of mail.domain.com I copied the IP Adress of the server. Solved the problem.

  212. Manfred Paleit

    Hello Paul,
    great script and very usefull to check our Exchange Systems.

    I’m getting 2 hours instead of 1780 in Powershell 3 with
    [int]$uptime = “{0:N0}” -f $uptime

    My fix is
    int]$uptime = “{0:N0}” -f $uptime.ToString
    The Uptime is now reported correctly.

  213. Lucas Falconi

    Hi !

    When I receive the e-mail with Exchange Server Health Check Summary, There is the following message:

    Server1 – Mail Flow Test Failed

    But at Exchange shell when I run Test-Mailflow SERVER1 -TargetMailboxServer SERVER2 , the result was succesfull.

    Everithing is working perfectly ! I don’t have any idea why i’m receving this error only at report.

    Can you help me ?

    1. Avatar photo
      Paul Cunningham

      Does that error always appear in the report or just that one time?

      1. Lucas Falconi

        Hy Paul !

        Always appear in report.

  214. Rob Derbyshire

    Hi Paul, thanks for this.
    Im running this on an Exchange 2013 Server, and am getting an error on the Mail Flow Test.
    Running Test-mailflow is successful, but this script returns an error for the Server it is running fromon

    Mail flow test: WARNING: Connecting to remote server ServerMBXpd01 failed with the following error message : The WinRM client cannot process the reques
    t. It cannot
    determine the content type of the HTTP response from the destination computer. The content type is absent or invalid. For more information, see the
    about_Remote_Troubleshooting Help topic.
    WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Supply 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. Supply a non-null argument and try the command again.
    At C:psHealthReportTest-ExchangeServerHealth.ps1:425 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

    1. Avatar photo
      Paul Cunningham

      Which CU are you running? I’ve seen reports of issues like this for some of the older CUs but AFAIK CU9 works fine.

      And have you configured the PowerShell virtual directory URLs? Mine are left as the server FQDN and the script works. I think some folks have seen similar errors when their PowerShell URLs are set to an alias.

      1. Brian

        I just got this same error CU11
        PSURL=FQDN

        Mail flow test: WARNING: Connecting to remote server xxx-xxxx failed with the following error message : The WinRM
        client cannot
        process the request. It cannot determine the content type of the HTTP response from the destination computer. The
        content type is absent or invalid. For more information, see the about_Remote_Troubleshooting Help topic.
        WARNING: Cannot validate argument on parameter ‘Session’. The argument is null or empty. Supply 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. Supply a non-null argument and
        try the command again.
        At C:tempTest-ExchangeServerHealth.ps1:426 char:19
        + Remove-PSSession $session.Id
        + ~~~~~~~~~~~
        + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

        Fail

          1. Matthew McDonald

            In my case we change all virtual directory internal URLs to our external mail URL (ex. mail.domain.com). When the script tries to connect to this host for mail flow, it fails with the same error as above. Any suggestions?

        1. Aftab

          managed to fix this. change the internal url for the powershell default to exchange server name with domain (FQDN) instead of load balancer URL, this worked for me.

  215. Krishna

    Hi Paul,

    Firstly, Thanks for the great superb.

    We are running Exchange 2013 environment, Script works fine. However, In the output I get “n/a” under Client Access Server Role Services, Hub Transport Server Role Services, Mailbox Server Role Services.

    All servers are multi role servers. Could you please help how to rectify/make required changes in the script to get the desired output.

    1. Avatar photo
      Paul Cunningham

      That part of the script uses Test-ServiceHealth so see you can run that cmdlet on its own.

      1. Krishna

        Thanks for the quick reply Paul.

        I’ve tried to change that part of script to the best of my knowledge which did not work.

        Would you mind helping me with exact lines which need updated/modified in the script for me to get the desired output.

        Thanks in advance.

        1. Avatar photo
          Paul Cunningham

          Don’t change the script, I’m suggesting you run Test-ServiceHealth on its own to see whether it returns an error or gives you some clue as to why the script is not working correctly.

          Also if your servers are running non-English language then there are extra steps explained in the article above for what you need to change to get that to work.

  216. Paul Slade

    Great script, many thanks.

    Paul.

  217. Carlos Rotver

    hello Paul!

    Thanks for an excellent script. I have installed 3 new Exchange Servers, two mailbox and one CAS/HUB, on a remote site.

    The weird thing, is that the script is running perfect, on the rest of the servers but on the new CAS/HUB. It returns an error:

    Unable to retrieve uptime. Could not test service health. Could not test service health. Could not test service health. Could not test service health.

    I´ve check WMI on the server, with no problem. These 3 servers are on a different site, but again the script is running fine on the mailbox servers.

    Any Clue that you could give me??

  218. Jijo Antony

    Thanks for this useful script.

    But,I am not getting any email after completed the successful execution of the script. I have changed my own SMTPsettings.

  219. Rana

    Amazing Wonderful..

    Love the script & the output is amazing :DDDD

    you are the best MAN :DDDD

  220. Steven

    Hi Paul

    How do I make this to send report to multiple recipients?

    I tried “user1; user2”, this ends up in an error.
    I also tried “user1, user2”, but only user1 ends up getting the report while user 2 seems to be chopped off.

  221. Kristijan

    Well i overlooked that the Exchange EdgeSync service was down. After starting service everything was fine.

    Thnx & regards!

  222. Kristijan

    Hello Paul,

    the script works fine until last Exchange Rollup 10 update from Microsoft when the Hub Transport Role keeps saying Fail ( – Hub Transport Server Role required services not running )…. but service is running and mail flow is just OK. Tested.

    I have Exchange 2010.

    Regards

    1. Avatar photo
      Paul Cunningham

      Run Test-ServiceHealth on the server and see if any of the required services are not running.

  223. Shahid

    Paul,

    It only shows fail when you run the script from scheduled task. When i run it manually from PS Console it shows all ok.
    It only shows fail for the server the scheduled task is running from. If i scheduled task from another server it will show fail for that server and the previous server will show pass.
    Any idea why this is happening.
    i am also looking to get mailbox count for each databases in this script. Is it possible for you to amend the script.
    Your help is really appreciated.

  224. Shahid

    Paul,

    I would like to request to you if you can add to get mailbox counts on each database in this existing script, that would be great. I trying to consolidate the report for our environment.

  225. Shahid

    Thanks for the reply.
    I ran test-servicehealth and it shows all OK.
    The problem is which ever server you pick to run this script from, it shows some service fail on that server.
    I then tried using Send-MailMessage at bottom of your script andded this report send as attachment and all looks OK.
    I think the problem occurs when we use -SendEmail parameter and report comes in a body message.

    For NashTek,
    You can add this command at the end of this script

    Send-MailMessage -To User1@xyz.com, user2@xyz.com -From admin@xyz.com -Subject “$reportemailsubject – $now” -Body “Test Message” -SMTPServer -Attachments

    i am too using this method to send report to multiple users.

  226. NashTek

    Hello Paul or anyone else that might be able to offer some insight,

    Hopefully this is an easy request. Please tell me how this script can be edited to send email to multiple recipients? I have tried separating recipients in the To: field by comma, semi colon and blank space but nothing works for me when my scheduled task runs. Specifying a single recipient works without issue.

    Kind Regards

    1. NashTek

      Here’s something I found from a similar issue that may have some relevance:

      The MailMessage constructor you are using only takes one email address. See the MSDN documentation http://msdn.microsoft.com/en-us/library/5k0ddab0.aspx

      You should try using Send-MailMessage instead because it’s -To parameter accepts an array of addresses

      Send-MailMessage -from from@email.mail -To $recipients -Subject “Disk Space Report – $Date” -smptServer smtp.server -Attachments $freeSpaceFileName

      Note: Send-MailMessage was introduced in PowerShell v2.0 so that’s why there are still examples that use other commands.

      The script is run from Scheduled Tasks on a Windows Server 2008-R2 server running Exchange 2010-SP3 Update Rollup-9 as follows;

      Action:
      Start a Program

      Program/script:
      C:WindowsSystem32WindowsPowerShellv1.0PowerShell.exe

      Add arguments (optional):
      -command “. ‘C:Program FilesMicrosoftExchange ServerV14BinRemoteExchange.ps1’; Connect-ExchangeServer -auto; C:ScriptsTestExchangeServerHealth.ps1 -ReportMode -SendEmail”

      Start in (optional):
      C:Scripts

      1. NashTek

        That’s what I decided as well. Thanks for the reply.

  227. Shahid

    Paul,
    Thanks for this wonderful script and the work you are doing to help people like us who do not much experience on writing the PS scripts.
    I am having one issue with report, the script runs fine without any errors.
    The server from which this script is executed it shows in the report that the server role as failed.
    I tried running this script on my HT/CAS, MBX role server and it shows same in the report.
    But when i execute the script -server parameter the report shows all green.
    e.g i am running the script from EXCH01 and generate the report for this only it shows all green, but when run the script against all server with scheduled task or from management shell from server EXCH01 which has HUB/CAS role then it shows HUB Transport Role as failed.
    Another thing i noticed is if i execute the script from EXCH02 which is in ignorelist.txt file then report comes out as expected, but if this server is not listed in ignorelist.txt file and the script is executed from this server then it shows role service failed for this server.
    I hope i have put down my issue in detail for you to understand and help me fix this.

    Thanks in advance for your help.

    Shahid

    1. Avatar photo
      Paul Cunningham

      Sounds like one of your servers has some services not running. Use Test-ServiceHealth to test that server.

  228. Sachin ladde

    Hello Paul,

    I would like to thank not just for this script, but for each and every blog that you have written as it is helping a lot to me in my day to day task.

    Regarding Test-ExchangeHealth script, I think for Exchange 2013 MA events or HealthReport should be added.

    I am looking for a Exchange 2013 report which will include all database and server health + managed availability health set command result (Get-HealthReport) for all the servers.

    I would also like to suggest to add few line to the script which will dig into Managed Availability Logs and find the number of occurrence of probe failure with error description.

  229. Gabe Foltz

    To clarify, I obviously can see that the “Test-Mailflow” cmdlet (at least) is being used, but I can’t tell where or what it is testing. (if it helps, I am running Exch 2010, with 1 Hub/CAS server, and a 2-server DAG, I’ll call them “MB1” and “MB2”. I have a single mail database, and it is active on MB1). Here are the results:
    —— Checking MB1
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 300
    Server version: Exchange 2010
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Public Folder databases mounted: Pass
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: *FAILURE*
    —— Finishing
    Done.

  230. Gabe Foltz

    Paul (or anyone else), please help!

    I had a backup problem over the weekend. My LOGS volume filled up, and my exchange database dismounted. Iwas forced to turn on circular logging and manually restart replication. My servers are both up and everything appears great–EXCEPT that TestExchangeServerHealth script is returning a FAILURE for “Mail flow test” on my active mailbox server.

    I have confirmed that my Exchange system is sending and receiving both internal and external email. None of my other tools (SolarWinds, EMC, Mail Flow Troubleshooter) are showing any issues. I tried turning on “-Log” to get more detailed information, but all the log file shows is the same generic info as the screen display.

    I have looked in the script, but frankly I am not a PS guru, and I can’t even tell what EMS commands are being used to test “Mail Flow”… Can someone help illuminate what calls are being made so I can at least replicate this failure outside the script?

  231. Tausif

    Thanks Paul!!

  232. Tausif

    Hi Paul,

    Really nice work!!!

    Can we customize it to show last backup done for databases.

    Usually we run the following cmd

    get-mailboxdatabase -status | ft name,last* -auto

    can we include it in script

  233. Frank

    Hi Paul,

    Thanks for the wonderful script.

    While there were several errors when script ran:
    The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    The term ‘Test-ReplicationHealth’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
    path was included, verify that the path is correct and try again.

    Do you have suggestion about what will be the cause ?

    Regards,
    Frank

  234. Harish Bajaj

    Running above scripts give output on screen no email to HTML file. I modified the email setting no error but no email is also being sent.

      1. Harish Bajaj

        I have saved the script and changed email details like To , from and server details.

        than ran the script from Exchange power shell..

  235. Chretien

    06/18/2015 13:10:20 —— Checking PVW0-EXCH-F-UL1
    06/18/2015 13:10:20 Checking DNS
    06/18/2015 13:10:20 DNS check passed
    06/18/2015 13:10:20 Checking ping
    06/18/2015 13:10:23 Ping test passed
    06/18/2015 13:10:23 Checking uptime
    06/18/2015 13:10:23 Uptime is 671 hours
    06/18/2015 13:10:23 Server is running Exchange 2010
    06/18/2015 13:10:23 Server roles: ClientAccess, HubTransport
    06/18/2015 13:10:23 Checking service health
    06/18/2015 13:10:24 Client Access Server Role Services status is Pass
    06/18/2015 13:10:24 Hub Transport Server Role Services status is Fail
    06/18/2015 13:10:24 Checking Hub Transport Server
    06/18/2015 13:10:24 Queue length is 1
    06/18/2015 13:10:24 Finished checking server PVW0-EXCH-F-UL1

      1. Chretien

        Yes all others parts are good, and I copy only the check of that server. Note that the server giving me that error is in a different AD Site. I am sure that, maybe there is something blocking it through the network. It’s really weird. Thanks for your suggestion.

        in which mail can I send you the whole log file?

        Thanks

        1. Avatar photo
          Paul Cunningham

          You can send me the log at paul at practical365.com, but I’m confused what you’re asking for help with. Is it a problem running the script, or is the script reporting a problem with one of your servers and you’re not sure what to do about it?

  236. Chretien

    Hello Paul,

    I cannot find it. It seems that it does not generate anything. I have checked everywhere and event use a tools to look for it without success.

    Thank you to guide me.
    I am looking forward to hearing from you.

    Regards

  237. Paul

    Hi Paul

    I can run the powershell scrip using .Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

    and receive the email and a copy of the report in html.

    The issue is with the task schedule as the scripts run but I am not receiving emails and log details
    In the task schedule I have used your recommended settings.

    My scheduled task settings for this script are:

    Run whether user is logged on or not
    Run with highest privileges
    Action: Start a program
    Program: powershell.exe
    Arguments: -command “C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -Log -SendEmail”

    could you please advice on this?

    1. Avatar photo
      Paul Cunningham

      What does the log file say? If you can’t find it then it may be writing to a different folder. Try searching your C: drive for the log file name, or change the “Start In” setting in the scheduled task to match where the script is located.

  238. Chretien

    Bonjour,

    Merci pour ce scripts, j’ai une error peux-tu s’il te plait m’aider parceque j’ai cet error pourtant mon transport server n’a pas de probleme.

    —— Checking PVW0-EXCH-F-UL1
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 505
    Server version: Exchange 2010
    Roles: ClientAccess, HubTransport
    Client Access Server Role Services: Pass
    Hub Transport Server Role Services: Fail

    Merci

    1. Avatar photo
      Paul Cunningham

      Run Test-ServiceHealth on that server and it will list the services that need to be started for the test to pass.

  239. Gregory

    When running the script on the “primary” machine the mailflow test fails for that machine. Is this script intended to be ran from outside of the actual exchange machines. The server is server 2012r2 and exchange 13 cu8.

    Actual error:
    Mail flow test: WARNING: Connecting to remote server failed with the following error
    message :
    Access is denied. 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:PowershellTest-ExchangeServerHealth.ps1:425 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail

  240. Admin

    Hi Paul,

    I get the following message when the scripts runs the Mail flow test: Warning: Connecting to remote server xxxxx failed with the following error message: The WinRM client cannot process teh request. The WinRM client tried to use Negotiate authentication mechanism, but the destination computer (xxxxxxx:80) returned an ‘accesss denied’ error. The script was running fine while I was testing before the error appeared. Please advise how to fix this error. Thanks.

  241. Essexboy

    Hi Paul, Great script!! Thanks I just want to create a Batch script to have this run, not necessarily through task scheduler. I need the report and email. Can you provide me the script for this? Report PS1 file is located in C:ScriptsExchange Health ReportTest-ExchangeServerHealth.PS1.

    Apologies if this is a simple request. Trying to get my head around scripting!!

    1. Avatar photo
      Paul Cunningham

      Just put the same info you’d use in Task Scheduler into a batch file instead. In the article above I shared my Task Scheduler configuration.

  242. Rich

    Hey Paul, great script! I’ve been using it for over two years now.

    I’m not sure if it has already been suggested, but I would like to see one small feature added – what server has quorum for each DAG. Currently, I manually use this:

    Get-DatabaseAvailabilityGroup -Identity DAG -Status | fl PrimaryActiveManager

    It would be nice to see this in your script as well. Just my $.02.

  243. SysAdmin

    It was a missing quote in one of the email fields. Thanks!

  244. SysAdmin

    Hello Paul – great script. I’m looking forward to using it. I am however getting an error message when I try to run it:

    At D:scriptsTest-ExchangeServerHealth.ps1:549 char:8
    + Write-Verbose $string21
    + ~
    Missing ‘=’ operator after key in hash literal.
    + CategoryInfo : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : MissingEqualsInHashLiteral

      1. SysAdmin

        Just the email section and I double checked all the values.

        1. Avatar photo
          Paul Cunningham

          Most likely issue is you’ve not closed quotes or brackets properly. Try the script without edits (just let it output to console). If that works then redo your edits and look for typos.

  245. Mohamed Ramadan

    Hi Paul,
    The script is amazing and running very smooth.

    I have a question:
    I have mixed environment 2010/2013, when I run the script against the 2010 CAS/hub server it runs very smooth on the default receive connector.
    when I run it against 2013 it doesn’t send email and require authentication.

    in the protocol logs, I’ve found that the script is authenticating with the 2010 server by the user that ran the script while this doesn’t happen on 2013.

    is there a way to do so or whay does it authenticate with 2010 and doesn’t do so with 2013?

    1. Mohamed Ramadan

      This is the trasport logs on both servers

      On 2010:

      220 2010Servername Microsoft ESMTP MAIL Service ready at Sun, 3 May 2015 11:47:59 +0300
      EHLO
      250-2010servername Hello [RemoteIP]
      250-SIZE
      250-PIPELINING
      250-DSN
      250-ENHANCEDSTATUSCODES
      250-STARTTLS
      250-X-ANONYMOUSTLS
      250-AUTH NTLM
      250-X-EXPS GSSAPI NTLM
      250-8BITMIME
      250-BINARYMIME
      250-CHUNKING
      250-XEXCH50
      250-XRDST
      250 XSHADOW
      AUTH ntlm
      334
      Set Session Permissions
      SMTPSubmit SMTPSubmitForMLS SMTPAcceptAnyRecipient SMTPAcceptAuthenticationFlag SMTPAcceptAnySender SMTPAcceptAuthoritativeDomainSender BypassAntiSpam BypassMessageSizeLimit SMTPSendEXCH50 SMTPAcceptEXCH50 AcceptRoutingHeaders AcceptForestHeaders AcceptOrganizationHeaders SendRoutingHeaders SendForestHeaders SendOrganizationHeaders SMTPSendXShadow SMTPAcceptXShadow
      DomainUsername ” the user that ran the script” authenticated
      235 2.7.0 Authentication successful
      —————-
      On 2013
      220 2013servername Microsoft ESMTP MAIL Service ready at Tue, 5 May 2015 08:20:55 +0300
      EHLO
      None
      250-2013server Hello [Remote IP]
      250-SIZE 36700160
      250-PIPELINING
      250-DSN
      250-ENHANCEDSTATUSCODES
      250-STARTTLS
      250-X-ANONYMOUSTLS
      250-AUTH NTLM
      250-X-EXPS GSSAPI NTLM
      250-8BITMIME
      250-BINARYMIME
      250-CHUNKING
      250 XRDST
      AUTH ntlm
      334 Inbound Negotiate failed because of LogonDenied
      User Name: NULL

      Tarpit for ‘0.00:00:05’ due to ‘535 5.7.3 Authentication unsuccessful’

      1. Avatar photo
        Paul Cunningham

        I can’t tell anything from that protocol log info because you’ve left out the receive connector detail.

        The default frontend connectors on Exchange 2013 allow unauthenticated SMTP to *internal* recipients. So if you have not created any custom receive connectors in Exchange 2013 it should work.

        If you *have* created custom receive connectors it’s possible that the custom connector is handling your SMTP connection. The way to tell is to look at the receive connector name in the protocol log entries.

  246. Jose Byron Gonzalez

    Or simply create a DL that includes those two people?

  247. Alexis Crawford

    Hi,

    Great scripts and Exchange information. In the script I want to be able to send the email 2 people.
    I’ve tried “email1″,”email2” this did not work
    “email1″;”email2” this did not work
    (“email1″,”email2”) this did not work
    (“email1″;”email2”) this did not work

    Any ideas?

    1. Erik

      did you try “email1;email2” ?

    2. Avatar photo
      Paul Cunningham

      As Jose suggests, use a DL for this. Much simpler to manage in the long run.

  248. Tim Klassen

    Great work Paul! I really enjoy your articles and scripts.

    One thing I get when running this script in my 2 server Exchange 2013 CU6 environment is a Kerberos error against the Round Robin DNS name when doing the Mail Flow Test on the server hosting the database.
    This happens as the computer object for the round robin DNS name doesn’t exist.
    Any input on getting this to test the actual computer name rather than the round robin DNS name?

    Thanks!

    1. Avatar photo
      Paul Cunningham

      Can you email me the full error or the full log file (use the -Log switch) to paul at practical365.com and I will take a look.

      Some earlier CU’s don’t run the script properly for some reason but yours is the first report of a Kerberos error, as far as I recall.

      1. Tim

        Did this ever get fixed? I’m experiencing the same with Exchange 2016 CU6, but only if I run it for all servers. If I run it against any individual server, mail flow checks pass. If I run it without the server name switch, it fails when connecting to the round-robin DNS name we use

        1. Avatar photo
          Paul Cunningham

          If the script is trying to connect to a PowerShell vdir that is configured with an alias instead of the server FQDN, I believe it fails unless Kerberos auth is fully set up and configured for your Exchange environment.

          1. Tim

            I apologize if I’m missing something, but does that still explain why running “Test-ExchangeServerHealth.ps1 -Server mailsrv17a” produces a mail flow test with a result of Success, but just running “Test-ExchangeServerHealth.ps1” show a failure on that same server (mailsrv17a)?

  249. Doug

    Hey Paul, do you have any recommendations for me if we have disabled the indexing service on all mailbox servers by design? My environment is 110TB and enabling indexing would require more storage than we want to procure at this time. Is there a way to ignore indexing completely without ignoring the rest of the services on the mailbox servers?

    Also, for some reason the log is never created in the directory I am running the script from, and I cannot find it anywhere else on the server. I haven’t modified your script so I am pretty confused.

  250. CR H.

    I’m having trouble setting this up as a scheduled task. I’m using the settings you provided in the post, running on a 2013 CAS server. Running the script manually works fine on the server, but when I set up a scheduled task the result is always successful, but I never receive the report. I’m running the task as a domain user that has org admin rights within Exchange.

    Any ideas?

    Thanks!

  251. Anthony

    Script runs flawlessly! I do have one question though. What if I want to check my Edge Transport Servers? Where do I edit the script?

    1. Avatar photo
      Paul Cunningham

      There’s no edit I can suggest. I haven’t written or tested any Edge server checks. Some of the tests may happen to work against Edge but that isn’t by design.

  252. Matt

    Fantastic script, thanks for all the hard work! It seems, however, the WinRM is back with CU8. Anyone else experiencing the same thing?

  253. shanif

    Hey Paul,

    Is there a way the dive space for each server in a DAG can show up on this report? or do you have another report that can give me that information?

    please let me know

    1. Erik

      Wow, that script of June Castillote is awesome!

      I made a less awesome and little simpler modification to the original script of paul. This will check if the free disk space is lower than a specific treshold. Let me know if you are interested in the less awesome solution 🙂

      Regards,

      Erik

  254. Nick Paolini

    Hello,

    This is a great script, love it. But, when I run the script my results say two of my three mailbox servers fail the “Mail Flow test. I verified each server with PS that mail does flow. The error message is below. It appears to have a problem with WinRM Client.

    Any help would be great.

    Mail flow test: WARNING: Connecting to remote server sjmmail01 failed with the following error message : The WinRM client cannot process the request. It cannot determine the content type of the HTTP response from the destination computer. The content type is absent or invalid. 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.2Test-ExchangeServerHealth.ps1:424 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    1. Mike

      Nick, I had the same error as you, I upgraded to CU7 and the script now works as expected

      Mike

  255. Erik

    Hi Paul,
    when running this scripts, some of the Exchange 2010 servers return:
    fyi: I am using v1.12 of the script.

    —->
    Mail flow test: Write-Log : The term ‘Write-Log’ is not recognized as the name of a cmdlet, function, script file, or op
    erable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:ScriptTest-ExchangeServerHealth.ps1:402 char:14
    + if ($Log) {Write-Log $_.Exception.Message}
    + ~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Write-Log : The term ‘Write-Log’ is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:ScriptTest-ExchangeServerHealth.ps1:416 char:14
    + if ($Log) {Write-Log $_.Exception.Message}
    + ~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    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:ScriptTest-ExchangeServerHealth.ps1:423 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand
    <—

    any idea what might cause this? It is pretty weird because not all the exchange 2010 servers return this error. Not all 2010 servers are running the same CU, but it does not seem to be bound to a specific CU (error occurs on servers with different CU levels).

    1. Avatar photo
      Paul Cunningham

      Whoops, a typo when trying to call the Write-LogFile function… must have been there for a while and gone unnoticed.

      I just pushed an update to Github and TechNet Script Gallery that should fix it.

  256. Phil

    This is a great script and I have been using it for years. However, recently in one of our environments where there is 2 CAS servers and 2 MBX servers, I am getting reports from the script saying ‘Could not test service health’. I run the script on two servers 30 minutes apart from each other. One server does not send the alert, so everything is ok, but the other started sending this regularly about a week ago.
    All other tests pass. but for each of the role services on each server, it shows Could not test service health. and ‘n/a’ in its own server roles.
    Does anyone have an idea what may have changed to cause this?

  257. IT

    Hi,

    We do have a strange issue with exchange 2013 where all the emails are in submission queue. All the test and checks are positive. Still cant fihure out why. The exchange server looks fine and seems no issue with it. All the emails are stuck in the queue and does nothing.

    1. Avatar photo
      Paul Cunningham

      Get-Queue | Get-Message | Fl

      That command will output a bunch of information about the messages in the queue, including any error messages (if any exist).

      1. IT

        Hi Paul,

        Thanks for the reply. I was able to clear the message queue by restarting the transport services which should do automatically pushing out emails.

        Hence, it is not the concern of messages in the queue but its not pushing out by itself.

        Exact Scenario: The email reaches the exchange server and just stuck there in the queue. Once the transport service is restarted, it pushes out few e mails and stops again.

        I had recreated the send/receive connectors but still doesn’t work.

        1. IT

          Just appending the error logs

          2015-02-05T00:14:43.859Z,08D208896C3835E1,SMTP,client proxy,>,Established connection to
          2015-02-05T00:14:44.258Z,08D208896C3835E1,SMTP,,-,Messages: 0 Bytes: 0 (Remote error from proxy client)

        2. Avatar photo
          Paul Cunningham

          If you do a few Google/Bing searches for things like “Exchange 2013 messages stuck in queue” you’ll find a lot of discussion around this topic. It is quite common, but can also be due to a wide variety of root causes. For example:

          http://thoughtsofanidlemind.com/2013/03/25/exchange-2013-dns-stuck-messages/

          First thing to check is whether you’re running the latest CU version of Exchange 2013 (currently CU7). Some of the earlier builds of Exchange 2013 did seem more prone to this type of transport issue.

  258. Mike

    Hi
    Thanks for the script, I can run it however I get an error on Mail Flow Test (see below)

    PS C:INSTALLSEXCHANGE_SCRIPTS> .Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail
    Initializing…
    WARNING: The file C:INSTALLSEXCHANGE_SCRIPTSignorelist.txt could not be found. No servers, DAGs or databases will be ignored.
    —— Checking EXCHANGE-SERVER
    DNS Check: Pass
    Ping Check: Pass
    Uptime (hrs): 141
    Server version: Exchange 2013
    Roles: Mailbox, ClientAccess
    Mailbox Server Role Services: Pass
    Client Access Server Role Services: Pass
    Unified Messaging Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 1
    Mailbox databases mounted: Pass
    MAPI connectivity: Success
    Mail flow test: WARNING: Connecting to remote server mail.DOMAIN.COM failed with the following error message : WinRM cannot process the request. The follo
    wing error occurred while using Kerberos authentication: Cannot find the computer mail.DOMAIN.COM. 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:INSTALLSEXCHANGE_SCRIPTSTest-ExchangeServerHealth.ps1:410 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    —— Finishing
    Sending email.
    Done.

    The report is emailed OK (I edited the smtp section within the script), I have run the script on all exchange server and get the same result, I think the problem may be due to a missing spn mail.DOMAIN.com but I do not know what it is to registered to, can you help?
    Thanks
    Mike

      1. Mike

        Hi Paul,
        I was running CU3, I’ve upgraded to CU7 and now its working (thank you very much) However the CU7 upgrade has made the ForwardSyncDaemon component inactive and I cannot start it!!!!

        Many Thanks
        Mike

  259. George

    Hey Paul,

    I would like to run this script for my environment. Does it require a downtime or anything? I just need to know if its ok to run during business hours or I need to put in a change control as it may cause a temporary down of the servers.

    Thanks

  260. Peter

    Hi Paul,

    Script looks fantastic, however I’m running into three issues.

    1. Test-ServiceHealth against Ex2007 HUB server generates Watson dump. Below is error message:

    ////////////////////////////////////////////////////////////
    Roles: HubTransport
    WARNING: An unexpected error has occurred and a Watson dump is being generated:
    Could not test service health. : System.Management.Automation.RemoteException: NotSpecified: (:) [Test-ServiceHealth],
    OutOfMemoryException
    ////////////////////////////////////////////////////////////

    2. Mail-flow test against Ex2007 ccr cluster just skips.
    3. Mail-flow test against Ex2013 (in dag) that holds active databases fails. Below is error message:

    ////////////////////////////////////////////////////////////
    Mail flow test: WARNING: Connecting to remote server webmail.interpipeline.com failed with the following error message :
    WinRM cannot process the request. The following error occurred while using Kerberos authentication: Cannot find the computer webmail.interpipeline.com. 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 isnot 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 X:Custom_ScriptsTest-ExchangeServerHealth.ps1:423 char:19
    + Remove-PSSession $session.Id
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand

    Fail
    ////////////////////////////////////////////////////////////

    Any help is greatly appreciated!

    1. Avatar photo
      Paul Cunningham

      For 1 and 2 , the script isn’t tested or intended to work against Exchange 2007 servers.

      For 3, that looks similar to an issue raised by someone else. I believe the problem is SSL validation when trying to do a remote PowerShell session. I haven’t looked into a fix yet but it is on my list.

  261. Prakash

    Hi Paul,

    I like this new script as it has all information in one script.

    But It’s not showing color in Trans Queue like green/yellow/read. though information is written clearly that warning with number of messages/pass/fail.

    over all good.

    Thanks,
    Prakash

    1. Avatar photo
      Paul Cunningham

      Whoops, that got broken with a recent update. I’ll make a note and push out a fix as soon as I can.

    2. Avatar photo
      Paul Cunningham

      This is fixed now in the latest versions available on TechNet or Github.

  262. Mohamed Salama

    Hi Paul,

    Great Script!
    Is it possible in version 1.10 to get the number of messages in the Queue in the e-mail report?

    1. Avatar photo
      Paul Cunningham

      Sure thing. Just pushed an update to TechNet and Github to include that change.

      1. Mohamed Salama

        Thanks for your support 🙂

  263. Adam Borders

    Paul-

    I ran into an issue with the script I wanted to let you know about.

    I was running this against my new 2013 environment and it was not detecting my LAG copies correctly. I traced it down to line 1326. if ($replaylagcopy.Key -eq $mailboxserver)

    What I found is that in my environment it was having an issue due to case sensitivity. I changed the -eq to a -match and it resolved the issue.

  264. Damian

    Paul,
    I downloaded the script and am running on my Exchange server via windows powershell. I am using the -reportmode $true and I get an error that says “The operation couldn’t be performed because object ‘True’ couldn’t be found on “my domain controller”. Any ideas? My DC’s are Server Core.

    1. Damian

      Nevermind..I see now you don’t need $true. Saw youtube video of this script being run and that was included.

  265. Ian

    I’d like express a little frustration at your comment in the script that “reportfile implies reportmode:$true”. After chasing for an hour or two why no file was being created, I decided to add -reportmode in addition to -reportfile parameter and suddenly the file is being created.

    TL;DR: -reportfile DOES NOT IMPLY -reportmode, despite documentation to the contrary. *shakes fist*

  266. Nikolas

    As for the command I am using, “-Command .Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail”

    1. Nikolas

      Paul,

      Awesome that answered my question. Thank you very much!

  267. Nikolas

    The script runs flawlessly in powershell and everything is passed or success, but I am not able to find the outputted .HTML file. Nor is it sending an email to the address I inserted. The relay is working without any issues, any ideas?

    1. Nikolas

      It looks like there are parameters that are set to false,
      ——————————————-
      [CmdletBinding()]
      param (
      [Parameter( Mandatory=$false)]
      [string]$Server,

      [Parameter( Mandatory=$false)]
      [string]$ServerList,

      [Parameter( Mandatory=$false)]
      [string]$ReportFile=”exchangeserverhealth.html”,

      [Parameter( Mandatory=$false)]
      [switch]$ReportMode,

      [Parameter( Mandatory=$false)]
      [switch]$SendEmail,

      [Parameter( Mandatory=$false)]
      [switch]$AlertsOnly,

      [Parameter( Mandatory=$false)]
      [switch]$Log

      )

      ———————————————

      Is this what I need to change in order for this to work?

      1. Avatar photo
        Paul Cunningham

        Mandatory=$false just means that they don’t need to be specified for the script to run.

        What is the exact command you’re running?

        1. Nikolas

          I am just running the script but my question is if I want this to push out the HTML file does something need to be modified or is the script doing this by default? Also I need it to send out the email in which I already added the smtp settings including testing via telnet.

        2. Avatar photo
          Paul Cunningham

          The script has multiple parameters/switches that are used to control the behaviour and output.

          The script also has built-in help. So you can run this command to see some examples of how to use the different parameters:

          [PS] C:Scripts>get-help .Test-ExchangeServerHealth.ps1 -Examples

          So if you want it to output both the HTML file and send the email, you would run:

          C:Scripts>.Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

  268. Mr. JIT

    Trying to download the script, but taken to my member content page and never gets me to the script download page.

  269. Mb

    Hi where do we download this script I cannot find the link anywhere

    thanks

  270. Mustafa Zain

    Thank you for your script.
    I have a little bug on the report. I run this report from Exch 2013 MBx server. So this server mail flow test always be failed.

    I replace the following line in the script to solve this problem:
    $result = Invoke-Command -Session $session {Test-Mailflow} -ErrorAction STOP

    with:
    if ($env:computername -like $e15mailboxserver)
    {$result = Test-Mailflow -ErrorAction STOP}
    else {$result = Invoke-Command -Session $session {Test-Mailflow} -ErrorAction STOP}

    Regards,

    1. BigGreg

      This fixed mt problem with Mail Flow tests failing. Thanks

    2. BigGreg

      This fixed my problem with Mail Flow tests failing. Thanks

  271. Amar Kanta

    Hi Paul,

    Thank you for the awesome script, but I was trying to send the report to multiple recipient but get is not sending , it is sending to only one address , I have tried putting , as well as ; ..any help would be appreciated..
    Amar

    1. Avatar photo
      Paul Cunningham

      Try sending it to a distribution group. That way you don’t need to modify the script any time a recipient needs to be added or removed, you can just do it in the group membership.

  272. Adam Borders

    I am in the process of migrating from 2010 to 2013. When I run the script on a system with the 2013 management tools it dies with the error: “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.”

    The error happens at line 1159: $tmpdags = @(Get-DatabaseAvailabilityGroup -Status)

    I currently have two DAGs. An Exchange 2010 and an Exchange 2013. The (Get-DatabaseAvailabilityGroup -Status) command works but the (Get-DatabaseAvailabilityGroup -Status) command gives the error. I can run the command without the -Status parameter just fine.

    If I run the same script on a system with the 2010 tools installed it grabs the 2010 Dag just fine.

    Thanks,

    Adam

    1. Avatar photo
      Paul Cunningham

      Some bugs with the script like that seem to pop up in co-existence scenarios.

  273. Gabe Foltz

    Paul, I was able to get this working with *very* little effort in my Exchange 2010 environment. Although I already have other monitoring tools in place, this handy little script will give me additional peace of mind. I even got it running as a task from my local Win7 workstation with no errors.

    If anyone cares, my task was setup like many others, except I omitted the path in the argument by simply specifying the “Start in” folder. My Arguments looked like this:

    -Command .Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

  274. Andy

    Hi Paul,
    These scripts are awesome and the results have impressed the right people in the places I have used them.
    I have been asked if it is possible to get the results in an xml format so they can be used in a system dashboard.
    Can you give me any pointers on adding thast to the script as my powershell isn’t that good yet
    TIA
    Andy

    1. Avatar photo
      Paul Cunningham

      I’ve never tried XML output for the report. I suspect it won’t easily work because so much of the code is spitting out bits of HTML code that get assembled into the final report.

  275. Juanita

    Hi, I’m looking for a script that would automatically run the following tests. All in one.
    Test-Servicehealth
    Test-ReplicationHealth
    Test-Mailflow
    Get-MailboxDatabaseCopyStatus
    Test-MapiConnectivity

    1. Avatar photo
      Paul Cunningham

      Sure. Have you looked at the script mentioned in the article above?

  276. Sean

    Where is the link to download the script(s). If no link how I am able to get it?

  277. Chris

    Hi
    Where can I download this script from… cant find the download button

  278. Pär Glanzén

    Hi, when I run this script on one of my exchange server i get that the Tcp listener failed, but when I use the script on another server it says that there is nothing wrong with the tcp listener on the first server.

    is this something in the script or should I look elsewhere to find out why I get different results?

  279. Ram

    Steve, the script is not downloadable !

    1. Ram

      sorry – it is. rgrds.

  280. June Castillote

    Thank you for this Paul.

    I found that the script only does MAPI test on Mailbox DBs and does not include Public Folder DBs.
    In effect when you have a Mailbox Server without Mailbox DBs, only hosting PF DBs, you get an “Unknown” result in the report.

    I modified the script to include PF DBs in the MAPI Test.

    ———-
    ####Combined the two arrays into one####
    [array]$totaldbs = $pfdbs + $mbdbs
    ———-

    Then in the MAPI Test Loop
    ———-
    Instead of the original:
    foreach ($db in $mbdbs)

    I changed it to:
    foreach ($db in $totaldbs)
    ———-

  281. Vishal Patel

    When I run the test-exchangehealth.ps1 script on Exchange 2013 in co-existence with 2007 I get an error

    EXCH002FP – Hub Transport Server Role required services not running. (this is an exchange 2007 server with both CAS and Hub transports roles)

    When I run the test-exchangehealth.ps1 script manually and send email all works apart from the above , however when I use task scheduler to run the script and send email I get MAPI test failed on all servers that do hold active DB. (But works if I run manually)

    • EXCH003FP – MAPI tests failed.
    • EXCH004FP – MAPI tests failed.
    • EXCH010FP – MAPI tests failed.
    • EXCH011FP – MAPI tests failed.
    • EXCH020FP – MAPI tests failed.

    1. Spyros

      Did you find any solution for the MAPI tests failed?

  282. Jeromy Baldridge

    Thank you very much for the script. It saved me a lot of time trying to come up with a less robust solution on my own.

    After quite some digging I found the two pain points that I was having with the scripts. I did not want an email on uptime errors or database preference errors. Line numbers are not exact because I added some comments and set some variables to $true so I wouldn’t have to remember switches. I am using v1.09 of the scripts.

    Somewhere around line number 771 I modified the line for Uptime :
    Switch ($uptime -gt 23) {
    For my purposes I changed 23 to 1. I also modified the error message lines that followed in the next couple lines for completeness.

    Somewhere around line number 1594 I modified the line for DB Preferences :
    $dagsummary += “$($line.Database) – $string62 $($line.Preference)”
    For my purposes I commented this line out so it would not trigger an email when the database was not active on the preferred server.

    1. Avatar photo
      Paul Cunningham

      Always great to hear people are successfully customizing the script for their own needs 🙂

  283. Gary Libero

    Hey Paul!

    We’ve been having issues with our Exchange 2010 server and I was VERY thankful to find your script here to help troubleshoot and check the health of our DBs. I’m not much a script guy, but I changed the email parameters, ran the script and when it gets to “mail flow check”, the script seems to stop (the PS window closes). Does that mean the script is not completing? I’m not receiving emails or seeing a file generated either way.

    Any help would be great appreciated!

    Thanks!
    Gary

    1. Rosario

      You may send me that piece of code you changed for review rosario-dot-carco{at}fhnw-dot-ch

    2. Avatar photo
      Paul Cunningham

      Gary, the window closes? If you’re running the script from a PowerShell window it should remain open and display any error that is causing the script to halt. Are you running it some other way?

      Otherwise, run it with the -Log parameter, which will write a log file that may assist with troubleshooting.

      1. Gary Libero

        Hey Paul!

        I got it working! I was right-clicking the file and selecting “run with Powershell”. Maybe it didn’t like that. I ran directly from PS and it completed fine.

        I can’t seem to get the email portion working. I set the parameters with all of our SMTP settings, but get nothing. I’ll have to review the notes again, but where is the parameter to just write an output file to the C Drive?

        Thanks!
        Gary

        1. Avatar photo
          Paul Cunningham

          You’ll find all the instructions and an FAQ on the page where the script is downloaded.

  284. André Winkler

    Hi @ll,

    at the moment im having problem with our Exchange 2013 and the mailflow test. Powershell tells me that there is a problem mit WIN-RM and negotiate Authentication.

    Another problem is on line 408 sign 19: Remove-PSSession $session.Id is not found. Is the variable defined somewhere?

    I am using Windows Server 2012 R2 in german with Exchange 2013 SP1.

    THX.

    1. André Winkler

      Hi again,

      yesterday i tried to run the script on the CAS and not on the Mailboxserver. Now it is running without any Errors.

      On all my Exchange 2010 Servers i have to run the script on the Mailboxrole. Can someone explain this?

      THX
      André

      1. Rosario

        As I told above, I scheduled the script to run on a CAS-Server, no problems. As I am developing another script, yesterday I tried to load the PSSnapin as Paul does to execute the exchange powershell commands from my Win7 Workstation and it quit with the Error “SnapIn could not be loaded”. So I do also wonder how much of the exchange powershell must be installed on my remote workstation, or whether we could get everything without installing any tools by opening a remote-powerShell-Session like this:

        $s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://phx-ex01.exchangelab.com/PowerShell/ -Authentication Kerberos -Credential (Get-Credential)

        Import-PSSession $s

        Of course this would only be a solution for interactive development. For scheduled execution during night, it may in any case be better to let the scripts run directly on the CAS-Servers where the needed user privileges are set up in the schedule itself (no need to ask for credentials)

        Rosario

  285. Aidan

    Hey Paul,

    Im getting the following error from one of my cas servers… other cas server works fine…

    Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.1 Client was not authenticated

    Ive checked permissions on all the connectors, tried using ssl and forcing credentials… any ideas?

    Much appreciated!

      1. Aidan

        Sorry! Should have looked, thanks a million Paul!!

  286. Jimmy Singal

    Hi Paul,

    Need your help:
    1. How do I pause the script when it finished checking? It seems the window will auto close.
    2. How can we send email to more recipients?
    3. If I create a shortcut using this command: %SystemRoot%system32WindowsPowerShellv1.0powershell.exe -ExecutionPolicy Bypass -File “C:scriptsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1” -ReportMode -SendEmail

    The script will run just fine and I will receive the email, but in a glance at the end of the result (on the powershell window) before the window close by itself I saw some lines in red, it looks like there are some errors.

    Thank you.

    1. Aidan

      Hi Jimmy,

      Answer1+3: At the end of the script you can add the noexit parameter e.g.

      %SystemRoot%system32WindowsPowerShellv1.0powershell.exe -ExecutionPolicy Bypass -File “C:scriptsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1″ -ReportMode -SendEmail -noexit

      Also running the script directly from a powershell window (rather than the scheduled task) will give the desired result.

      E.G. from powerhsell “C:scriptsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1 -ReportMode -SendEmail ”

      Answer 2:

      1 option would be to just create a Distribution list on the exchange with the desired users.

      The other option would be to add the accounts into the script like so:
      $To = “user1@domain.com,user2@gmail.com,distrolist@domain.com”

      Hope that helps,
      Aidan

      1. Jimmy Singal

        Hi Aidan,

        Thanks for your reply.
        Looks like the it works for my question 1 and 3.
        But for the email I have tried with the commas, it will only send to the first recipient. I haven’t created a distribution list.

        1. Aidan

          Sorry Jimmy, my bad!

          I wasnt looking at the script…

          Remove the To parameter from the array and below it create a variable with the smtp addresses:

          Line numbers 109-116

          $smtpsettings = @{
          From = “exchangeserver@exchangeserverpro.net”
          Subject = “Exchange Server Health Report – $now”
          SmtpServer = “smtp.exchangeserverpro.net”
          }
          $To = “user1@domain.com”,”user2@domain.com”,”user3@domain.com”

          Now add the -To parameter in the send-mailmessage function:

          Line numbers 1528-1530
          Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -To $To -Encoding ([System.Text.Encoding]::UTF8)

          That should be that!

        2. Avatar photo
          Paul Cunningham

          Seriously, just use a distribution list. Then you don’t need to edit the script every time your list of recipients changes.

        3. Rosario

          It worked for months as Paul programmed it. But for a strange reason I did not track back, it began to send the eMail only to the first person around January or February. I guess Aidans solution should be

          $to = “user1@domain.com,user2@domain.com,user3@domain.com”

          with only one pair of “” – Rosario

        4. Jimmy Singal

          Thanks Paul & Aidan,

          I have not tried Aidan’s solution yet, as I am just using the distribution list for keep the thing simple.

          To wrap up at this point, my task scheduler is being used to run the script from inside a batch file. Not sure why I keep having problem running the script if I specify it directly in the task scheduler.

          Also don’t forget to use @echo off at the beginning if not the task will keep running and running.

        5. Rosario

          Scheduling the powershell script is a little bit tricky.

          Program/Script: C:WindowsSystem32WindowsPowerShellv1.0powershell.exe

          Add argument: -Command “& C:psScriptsCheckExchangeServerHealth.ps1 -sendEmail”

          Start in: C:psScripts

  287. Robert

    Disregard ran this Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass and good to go. Thanks!

  288. Robert

    Paul,

    When I run the script I get not digitally signed error… ***HELP*** 🙂

  289. Jose Byron Gonzalez

    Hello and thanks for another wonderful script, Paul.

    Also related to the ignorelist.txt a rather silly question but one that’s vexing me: is it supposed to have any particular format or structure? Or a simple line-by-line list of servers, databases, DAG, etc?

    Is there a way to limit the scope to a single AD site (or exclude others)?

    Thanks so very much. You The Man, man!

    1. Avatar photo
      Paul Cunningham

      Simple line by line list, yes.

      You can customize it any way you like really. The builtin parameters provide some flexibility but everyone has different needs.

      The script just uses the Exchange cmdlets. So if you want Get-ExchangeServer to return just the servers in a site, modify that line of the script accordingly.

  290. Or Elim

    Did anyone managed to migrate this wonderful script to support Exchange 2007?

  291. Rob

    Love the script, I am having one error though, it will not call the ignorelist.txt file. It says “Warning: The file at …ignorelist.txt could not be found. No servers, DAGs, or databases will be ignored.” Is there a fix for this?

    Thanks.

    1. Avatar photo
      Paul Cunningham

      The script looks for the file in the current directory. Are you running the script from the directory where it is stored, or running it from a different directory?

  292. Michael Wiskman

    Great script. Very good to show customers. They know that green is good and red is bad. Then it is easy to explain that you have to fix errors in their environment.

    Thank You Paul.

  293. luis

    Thanks Paul. !!!!!!!!!!!!!!!!!!

    Perfect work.

  294. martinezjrj

    Brilliant! i should have known to retrace steps… like i said before, “NEWB”

    i was missing a double quote at the end of the smtp server name string!

    Thanks! wish there was a way to buy you a beer or cup of coffee!

    Cheers!

    Joel

  295. martinezjrj

    Paul thank you! This is probably a newb issue but i keep getting this error when i run this and cant seem to figure it out…

    [PS] C:scripts>.Test-ExchangeServerHealth.ps1 -Reportmode -Sendmail
    Unexpected token ‘Mailbox’ in expression or statement.
    At C:scriptsTest-ExchangeServerHealth.ps1:327 char:19
    + $mbrole = “Mailbox <<<< Server Role"
    + CategoryInfo : ParserError: (Mailbox:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    the error refers to the section in the script where variables for the server roles are initialized, here:

    # The server roles must match the role names you see when you run Test-ServiceHealth.
    $casrole = "Client Access Server Role"
    $htrole = "Hub Transport Server Role"
    $mbrole = "Mailbox Server Role"
    $umrole = "Unified Messaging Server Role"

    Thank you

    Joel

      1. martinezjrj

        Yes Paul i did but only to try and narrow down the issue. Running the script as is, with only the email settings modified, produces the same error. Sorry for the confusion. i posted the error produced when using the modified order, but posted the original code as reference. My bad!

        the original code:
        # The server roles must match the role names you see when you run Test-ServiceHealth.
        $casrole = “Client Access Server Role”
        $htrole = “Hub Transport Server Role”
        $mbrole = “Mailbox Server Role”
        $umrole = “Unified Messaging Server Role”

        i get this error:
        [PS] C:scripts>.Test-ExchangeServerHealth.ps1 -reportmode -sendmail
        Unexpected token ‘Client’ in expression or statement.
        At C:scriptsTest-ExchangeServerHealth.ps1:327 char:19
        + $casrole = “Client <<<.Test-ExchangeServerHealth.ps1 -Reportmode -Sendmail
        Unexpected token ‘Mailbox’ in expression or statement.
        At C:scriptsTest-ExchangeServerHealth.ps1:327 char:19
        + $mbrole = “Mailbox <<<< Server Role"
        + CategoryInfo : ParserError: (Mailbox:String) [], ParseException
        + FullyQualifiedErrorId : UnexpectedToken

        I have a Single Exchange 2010 Server SP3 (All Roles – no Unified Messaging) running on Windows Server 2008 R2 Standard SP1.

        Could it be SP3?

        thank you

        Joel

        1. Avatar photo
          Paul Cunningham

          The problem will most likely be where you made changes (to the SMTP settings) and haven’t closed a set of quotes properly.

  296. Jackson

    I found this took quite a while to run in a larger environment, 14+ hours. I was able to cut that time down to just a few hours with modifying the Test-E15MailFlow function, line 372 to simply add the -ADPropertiesOnly flag. Running the script with -Verbose I saw this is where it was hanging up. I hope it can help others!

    Write-Verbose “Creating PSSession for $e15mailboxserver”
    $url = (Get-PowerShellVirtualDirectory -Server $e15mailboxserver -ADPropertiesOnly | Where {$_.Name -eq “Powershell (Default Web Site)”}).InternalURL.AbsoluteUri

  297. Richard

    I have tried this on our Exchange 2010 set up. It reports a FAIL for the ‘Mailbox Server Role Services’ for one of our mailbox servers, but I’m not sure where to check why this is failing. I have looked at the script and couldn’t find out what test it is running for this. The server concerned seems to be running fine, our backup mailbox server gets a Pass for this test. A look at the logs on the server shows nothing amiss either.

    What does ‘Mailbox Server Role Services’ actually test?

  298. James Ledgard

    Brilliant script. Thanks for the hard work you and the others put into this.

  299. Andre Winkler

    Hi Paul,

    i would like to run the script as scheduled Task every morning and send the Report as mail. I want to use a dedicated taskuser that has no domainadmin rights. Which rights are necessary that the script is runninig successfull?

    At the Moment i get Errors checking the mailboxservice, Transport Queue and the mail flow test. When i run the script as Domain admin everything works fine.

    1. Avatar photo
      Paul Cunningham

      The minimum I’ve found to work is an account with Exchange Org view-only rights, local admin on each Exchange server, and also local admin on the server running the scheduled task (that last one bothers me, but I haven’t had time to work out anything different).

      1. sajeev

        I tried, but stil unable to read the database mounted information and also the Transport Queue info.

    2. Andre Winkler

      Hi Paul,

      thanks for your quick answer. I’ve tried to run the script as SYSTEM on the Exchange Servers. On most of the Systems it’s running (Exchange 2010), only on 1 Exchange 2007 Server it won’t. I gave the taskuser Organization Management and Server Management and local admin on the Exchange Server and it is running now.

      We have found a Problem with line 275: [int]$uptime = “{0:N0}” -f $uptime

      When the line is commented out the uptime is shown correctly. If the line is active the uptime is always shown with 2 hours. Maybe this behavior is because we use german OS?!

      So far everything works fine. Great Script.

      Greetings
      André

      1. Rosario

        Dear André, I work at the FHNW but we run the servers in english, never in german. But I had the same problem and Simon, Oleg and Andrew already documented the issue here. I did it too and wrote these lines in one of my previous posts:

        $uptime = [math]::round((New-TimeSpan $laststart $now).TotalHours,0) #Cr: rounded instead of int truncation
        #Cr: removed to avoid string and int conversion/display problems: [int]$uptime = “{0:N0}” -f $uptime
        #Cr: this could also be a fix, coming from Paul himself:
        #$timespan = (New-TimeSpan $laststart $now)
        #[int]$uptime = “{0:00}” -f $timespan.TotalHours

        1. Andre Winkler

          Dear Rosario,

          thanks for your Response.

          I work at a Application Service Provider with many different customers. So we have to take what we get 🙂 , German, Englisch, Nederlands and else.

          It was not a big Problem for us. After we commented out the line everything works fine und the uptime is shown correctly.

          Many Greetings from Germany.
          André

      2. Avatar photo
        Paul Cunningham

        Download the latest script version (v1.07), it includes a fix for that uptime bug as well as localization strings for non-English systems.

  300. Noor

    Hi Paul,

    I am getting an error ” Write-Error : The operation couldn’t be performed because object ‘True’ couldn’t be found on ‘DC.xxxx
    .prd’.
    At C:scriptsExchangeTest-ExchangeServerHealth.ps1:479 char:14
    + Write-Error <<<< $_.Exception.Message
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Microsoft.PowerShell.Commands.WriteErr
    orCommand"

    Please help.

      1. Noor

        Hi Paul,

        I am using ” .Test-ExchangeServerHealth.ps1 -ReportMode $true -SendEmail $true “

        1. Noor

          Hi Paul,

          It’s working, Thanks for the Great Script.

        2. Noor

          Thanks Paul

  301. Andrey Ganimedov

    Nice script. Good job! Thank you Paul
    And again in large environment quite time consuming.
    Modification only in one line saved more than 1 hour in my case.

    From: [array]$activedbs = @(Get-MailboxDatabase -status | Where {$_.MountedOnServer -eq ($server.fqdn)})
    To: [array]$activedbs = @(Get-MailboxDatabase -status -Server $server | Where {$_.MountedOnServer -eq ($server.fqdn)})

    1. Rosario

      That’s true. I noticed great speed improvements when executing exchange power-shell cmdlets simply by indicating, e.g. a specific Active Directory Domain Controller to use instead of letting it blank and letting the system choose one (where applicable of course).

  302. Henrik

    Hi!
    Thanks for the great script!
    I’m getting Failed on Mail Flow Test for the server on which I’m running the script. I have tried 3 servers with the same result. Any ideas?
    /Henrik

  303. OzDM

    PowerShell Scripts

    Access the script files and additional usage guidance.

    Test-ExchangeServerHealth.ps1 Script
    Get-DAGHealth.ps1 Script
    Get-MailboxReport.ps1 Script
    Get-DailyBackupAlerts.ps1 Script

    On this page there is not download option: However it does ask me to join.

    23770 downloads so far.
    This script is available for download by Exchange Server Pro Insiders. Join here it’s free.

    Looking at the code for ExchangeServerHealth code it is not the script referenced in this article. Is this article refering to Get-MailboxReport.ps1?? I can’t see any script name in the article at all, hence my confusion.

  304. OzDM

    I have signed up, why does it still request i ‘join up’ to download this script?

      1. OzDM

        I only see 4 scripts. Is that all the content there is?

        1. Avatar photo
          Paul Cunningham

          At the moment the insider access gets you 4 scripts and 1 free ebook. The next planned addition is the Exchange 2013 Boot Camp videos that I’m working on.

        2. OzDM

          How do I get access to more scripts? I am interested in the exchange backup reporting and this script.

        3. Avatar photo
          Paul Cunningham

          The Get-DailyBackupAlerts.ps1 script is available on the same members page.

  305. Phil Smith

    Paul,
    Great work, thank you.
    I have one question about version 1.06. In an earlier version I was able to exit out before it sent the report if there were no failures. Is it possible in this version? We manage several Exchange environments where we schedule it to run every 30 minutes and only want the report when there is a failure.

    1. Avatar photo
      Paul Cunningham

      Using the -AlertsOnly switch will suppress the email unless there is a warning or error to report.

  306. Khalid

    Hi
    I try to run the script but after sometime I received the following error

    Write-Error : The operation couldn’t be performed because object ‘True’ couldn’t be found on XXXXXXXX (DC)
    ‘.
    At C:UsersXXXXXXDesktopTest-ExchangeServerHealth.ps1:401 char:14
    + Write-Error <<<< $_.Exception.Message
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Microsoft.PowerShell.Commands.WriteErr
    orCommand

      1. Khalid

        .Test-ExchangeServerHealth.ps1 -ReportMode $true

        1. Avatar photo
          Paul Cunningham

          Ok. Please double check the help info included with the script. Correct syntax is:

          .Test-ExchangeServerHealth.ps1 -ReportMode

  307. TO:
    [int]$uptime = (New-TimeSpan $laststart $now).TotalHours
    [int]$uptime = “{0:N0}” -f $uptime

    1. Avatar photo
      Paul Cunningham

      I have a fix coming in the next version. In the meantime try changing those lines to:

      $timespan = (New-TimeSpan $laststart $now)
      [int]$uptime = “{0:00}” -f $timespan.TotalHours

      1. Rosario

        As I had a display-Problem, this is what I did in the version of the script I downloaded from here

        #[int]$uptime = (New-TimeSpan $laststart $now).TotalHours
        #[int]$uptime = “{0:N0}” -f $uptime

        #Cr: changed the above two lines as following:
        $uptime = [math]::round((New-TimeSpan $laststart $now).TotalHours,0) #Cr: rounded instead of int truncation
        #Cr: removed to avoid string and int conversion/display problems: [int]$uptime = “{0:N0}” -f $uptime

        1. Avatar photo
          Paul Cunningham

          Glad you’ve worked out a fix. I’ve got a different fix coming in the next version of the script which I hope to release very soon. Hopefully that also works for you 🙂

  308. Hi Again Paul,

    I found how to fix:

    Changed lines 615,616
    From:
    [int]$timespan = (New-TimeSpan $laststart $now).TotalHours
    [int]$uptime = “{0:N0}” -f $timespan

    TO:
    [int]uptime = (New-TimeSpan $laststart $now).TotalHours
    [int]$uptime = “{0:N0}” -f uptime

    And now all information are correct in report!

    Thanks!

  309. Hi Paul,

    I have a problem with last version of your script:

    Uptime (hrs): Cannot convert value “1 341” to type “System.Int32”. Error: “Input string was not in a correct format.”
    At C:ScriptsServerHealthTest-ExchangeServerHealth.ps1:616 char:17
    + [int]$uptime <<<< = "{0:N0}" -f $timespan
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException


    As i can see – this happens only on servers with uptime more than 1000 hours – may be because it is reporting time with space: 1(space here)341 hours

    How can i fix it ?

    Thanks again for this mega script!

  310. Atul Mangla

    Hi Paul,

    i have run this script on exchange server 2010 and in our environment we have exchange 2003 also.

    so i want to ignore ex 2003 server and i have mention server name in ignorelist.txt file as per like below.

    “test1″,”test2″,”test” etc.

    but after that when i run this script it’s don’t ignore this server.

    can you help please where i am wrong and give me exact direction how i should write name in txt file.

    Regards,
    Atul

    1. Avatar photo
      Paul Cunningham

      Place the server names in the ignorelist on one line each, eg

      server1
      server2
      server3

  311. Vidya Sagar

    Hi Paul,

    Very nice script and it helped me to get check the status daily morning.
    I have scheduled the script in windows server 2008 where management tools installed and it is running fine.
    Now i am planing to decommission the server so i have scheduled the same script in one of the CAS server.
    i am getting correct result for all other exchange servers’ health but for the server from where task schedule configured i am getting – Client Access Server Role required services not running.

    I have tested the script from manually running it and no errors reported. But if i run the schedule task i am getting services error for that specific exchange server from where i ran the schedule.

    I don’t have any clue why this is happening.
    Could you please help me..

  312. Sanju

    Dear Paul,

    Can we please add white space, Free DB disk space and Free Log Disk space free in the next release.

    Regards

    1. Rosario

      I did it in my version. Unfortunately you have a lot of lines to add to generate the whole tables for output. I am out for vacations but I can send you my version if you like by eMail.

  313. Sathya Paul

    We are Exchange 2007 SP3 (CCR)… when i run the script it comes with warning as below:

    WARNING: The Windows PowerShell snap-in
    ‘Microsoft.Exchange.Management.PowerShell.E2010’ is not installed on this
    machine.

    tried below link still the same:
    http://thwack.solarwinds.com/thread/58501.

    plz help

    1. Avatar photo
      Paul Cunningham

      The script is designed for Exchange 2010 and 2013. It loads the management snapin for those versions, not for 2007.

      You could replace the line in the script so that it loads the 2007 snapin instead, but you’ll run into other issues that the script simply isn’t designed to handle.

      So there will be some work ahead of you to customize it for your environment. But you’re welcome to take the script and modify it however you wish.

      1. Sathya Paul

        if i am not wrong below is where i need to change…. need some help as to where and what changes to be done.

        #Add Exchange 2010 snapin if not already loaded in the PowerShell session
        if (!(Get-PSSnapin | where {$_.Name -eq “Microsoft.Exchange.Management.PowerShell.E2010”}))
        {
        Write-Verbose $initstring1
        if ($Log) {Write-Logfile $initstring1}
        try
        {
        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction STOP
        }
        catch
        {
        #Snapin was not loaded
        Write-Verbose $initstring2
        if ($Log) {Write-Logfile $initstring2}
        Write-Warning $_.Exception.Message
        EXIT
        }
        . $env:ExchangeInstallPathbinRemoteExchange.ps1
        Connect-ExchangeServer -auto -AllowClobber
        }

        1. Avatar photo
          Paul Cunningham

          Replace the Microsoft.Exchange.Management.PowerShell.E2010 with the name of the Exchange 2007 snapin, which I believe is Microsoft.Exchange.Management.PowerShell.Admin

          Also remove these lines:

          . $env:ExchangeInstallPathbinRemoteExchange.ps1
          Connect-ExchangeServer -auto -AllowClobber

  314. Andrew

    Hi Paul,

    I am using the script: Test-ExchangeServerHealth.ps1

    Does the above script report on the DAG Status? Because when i run it I can’t see a reference to the DAG?

    Could just be me 🙂

    Cheers

    1. Avatar photo
      Paul Cunningham

      If you use the option to send an email report or output the report to a file it will include the DAG status. I’m working on adding the DAG status into the console output as well.

  315. Ray Cockshell

    Hi Paul
    We have been using the script successfully for a few months in a large government site.
    We have some databases (mainly used for Journaling) that we want to report on (they have DAG copies), but they do not contain Content Indexes . The IndexEnabled property is set to $False. The end result is a fair bit of red in the report about both Healthy and Unheathy Content Indexes.
    Rather than me butcher your elegant scripting, can you add to the wish list for future versions a capability to either list CI enablement and/or change the Healthy/Unhealthy status to indicate Not Configured (or similar) in a neutral colour.
    Regards
    Ray

    1. Avatar photo
      Paul Cunningham

      Interesting. Not a scenario I’d considered. Probably won’t be too hard to account for that in a future version.

  316. Erik J

    I get one more error, thats I (who is a beginner on this) dosent understand:

    This I get when i start the script:

    [PS] C:Script>.Test-ExchangeServerHealth.ps1 -Log -SendEmail
    Initializing…
    Update-TypeData : The following error occurred while loading the extended type data file:
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binexchange.types.ps1xml : File skipped because i
    t was already present from “Microsoft.PowerShell”.
    At D:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1:94 char:17
    + Update-TypeData <<<< -PrependPath $typeFilePath
    + CategoryInfo : InvalidOperation: (:) [Update-TypeData], RuntimeException
    + FullyQualifiedErrorId : TypesXmlUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand

    Update-TypeData : The following error occurred while loading the extended type data file:
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binExchange.partial.Types.ps1xml : File skipped b
    ecause it was already present from "Microsoft.PowerShell".
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binexchange.types.ps1xml : File skipped because i
    t was already present from "Microsoft.PowerShell".
    At D:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1:104 char:16
    + Update-TypeData <<<< -PrependPath $partialTypeFile
    + CategoryInfo : InvalidOperation: (:) [Update-TypeData], RuntimeException
    + FullyQualifiedErrorId : TypesXmlUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand

  317. Erik J

    When running the script with modifyed smtp settings i get this:

    Send-MailMessage : The specified string is not in the form required for an e-mail address.
    At C:ScriptTest-ExchangeServerHealth.ps1:1825 char:20
    + Send-MailMessage <<<< @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF
    8)
    + CategoryInfo : InvalidType: (Exchange server ADMIN:String) [Send-MailMessage], FormatException
    + FullyQualifiedErrorId : FormatException,Microsoft.PowerShell.Commands.SendMailMessage

    1. Avatar photo
      Paul Cunningham

      “The specified string is not in the form required for an e-mail address.”

      You should double check the email address you’re trying to use.

      1. Erik J

        Thanks, my fault, the from adress was wrong.

  318. Tony Holdgate

    W’ve been using this for some months now- great script. We had an issue over the weekend where a mailbox server manually had the exchange services stopped and then was shutdown. However the windows failover clustering service was not stopped and (I think) because the server was shutdown before this service realised the services were gone, the failover did not happen.

    What this made us realise is that even though clustering is a windows server service- its a fairly critical part of a DAG and it would be nice to monitor the service’s availability. Practical or a folly?

    1. Shane Bryan

      We monitor that, but in real-time as part of our network monitoring setup. We only run this script in the morning, as Paul says – to identify overnight issues – and then once more in the afternoon.

      If key windows services fail on a server, we prefer to know about it immediately rather than waiting for the scheduled task running this (awesome) script.

      (we’re using IPMonitor from Solarwinds).

      Cheers Shane.

      1. Tony Holdgate

        yep we should be doing that also….but working in a govt dept these things take too long. So we tend to monitor our own to make sure. However I’m putting the request in with the relevant area

  319. christian

    Hi,
    Don’t know what I am doing wrong but I don’t get any html output, if I export it to an html file it opens an empty web file. I tried both via the command line and task sceduler. the email is beeing send to me but I only see; “Exchange Server Database Availability Group health check results as of dinsdag 27 augustus 2013 17:14:12”

    Only thing I changed are the mailsettings.

    Anybody a clue?

    Command; -command c:scriptsGet-DAGHealth.ps1 -detailed -sendemail

    I run it from my only exch2010 server.

    1. christian

      the script Get-DailyBackupResults.ps1 works fine though..

      Get an nice report in my mailbox.

  320. Sanju

    Hi Paul,

    I was modifying the Script and want to add RPC connection test.

    # Start RPC Connections Test

    if ($IsCAS)
    {

    $RPC = $null
    $RPC = Get-Counter “MSExchange RPCClientAccessConnection Count” | select -expandproperty CounterSamples | select CookedValue
    $serverObj | Add-Member NoteProperty -Name “RPC Connections” -Value $RPC -Force
    if ($Log) {Write-Logfile “RPC Connections is $RPC”}
    }

    #END – RPC Connections Test

    However the above does not works and errors out

      1. Sanju

        Thanks for the script though

        There is no output on shell and i f I use the same code as in transport queue it gives out the queue length. I will get back to office and share the correct output

  321. Paul B

    Paul, thanks for your effort in producing this script, I enjoyed seeing Green across the board! 🙂
    Brilliant job and very much appreciated!

  322. Doug

    Love the script. Love seeing all of the GREEN font. However, I received one big red FAILURE on one test on one of the servers. It was the test-mailflow cmd. Everything else was green. All services were running. Test-MAPIConnectivity. But not test-mailflow. Test-mailflow from other server, even in the other datacenter, to the subject servers succeeds. But test-mailflow from the subject server, even to itself. I can’t find much on troubleshooting this event. Do you have any suggestions? Can the system mailbox be reset somehow? I’m at a loss as to how to best deal with this failure.

    Thanks

    1. Doug

      Never mind. Found it. Turned out to be a duplicate system mailbox in AD. Had the same GUID, but was appended with “CNF:” and another GUID. Microsoft said it was near impossible for this situation to occur. Guess I just got lucky. I deleted the duplicate System mailbox. All is good now. Thanks.

  323. Aidan

    Paul you are a legend! Really appreciate the help 🙂

    Keep up the great work!!

  324. Aidan

    Hi Paul,

    Whats the best way to exclude the Edgetransport service from being listed your array ? I love the script but dont want to start sending it to my team with big red markers saying service Failure when we arent using it 🙂

    P.S. I have zero powershell experience but getting into thanks to this 🙂

    Appreciate any help!!!

    Kind regards,
    Aidan

    1. Avatar photo
      Paul Cunningham

      If you mean the Edgesync service on Hub Transport servers, then the solution is to set the service to Automatic startup and start it.

      1. Aidan

        Hi Paul,

        You are correct but the service will not start as we are not using it. I can see in your other article relating to the event ID 1045 (which I receive when trying to start it) the solution is to create the configuration object New-EdgeSyncServiceConfig -Site “my site”

        Are there any implications to be aware of or prior criteria?

        Appreciate the help!!

        Kind regards,
        Aidan

        1. Aidan

          I should also probably mention its a 2 CAS and 2 DAG server array we use with cisco ironports in front to handle antispam etc..

        2. Avatar photo
          Paul Cunningham

          No implications that I’m aware of. The test cmdlet expects the service to be running, and I’ve always had it running even when no Edge servers are present.

  325. sounder

    Hello Paul,

    We have 6 exchange servers in the same site with typical exchange installation i.e. Hub, ,Mailbox and CAS.

    For Example below are the exchange servers:

    mailmxexch01
    mailmxexch02
    mailmxexch03
    mailmxexch04
    mailmxexch05
    mailmxexch06

    i ran the below script on mailmxexch06 exchange server

    .Test-ExchangeHealth2.ps1 –reportmode $true –reportfile ServiceHealthStatus.html

    result is generated in ServiceHealthStatus.html file .

    My question 1 : If i run the above mentioned script on mailmxexch06 exchange server , what will be the source server for mail flow?

    IF the source server is mailmxech06 (where i am executing the script) then what will be the sending email addres and recipient email address for the mail flow test?

    My second question 2: is this script is for both inbound mail flow test as well as for outbound mailflow test? OR this test only for outbound? .

    Question 3: How is the test for the mailflow performed?

    protocol logging is enabled on the above all 6 servers , i didnt found any SMTP Send OR Recieve logs?

    Question 4: To send a test email from source server to target server , we need sender and recipient email address right? what wll be the sender/recipient email addresses in the above script?

    please suggest me.

  326. Rance

    Is there any way to remove a specific role from the list. We dont have any Unified Messaging Servers in our org and I’d like to remove it from the report.

    1. Avatar photo
      Paul Cunningham

      Sure. Open the script in a PowerShell editor and remove those parts from the report section.

  327. Kelley

    I found the cluster problem. It was a rogue network with only IPv6 addresses created by the new NICs before addressing. The other issue is a DNS problem where the A record is disappearing. I really appreciate this script and all the other things you do for the Exchange community.

  328. Kelley

    I’ve been running the script for a while now and love the latest version. I recently changed nics in my server to vmxnet 3 and they all seem to be running fine. When I run the script at the command prompt all servers tests pass as well as the DAG tests. When I run it as a scheduled task and send email I get the following error on one of the HT/CAS boxes: “Could not test service health”. This occurs in all four columns regarding roles. Any idea why?

    Both tests, command line and scheduled, report that the cluster network for each of my three mailbox servers has failed. However, the cluster appears fine in the console and databases can be moved at will. Any idea why this would be marked as failed?

  329. Rosario

    I might be a bit late, but I just integrated some new figures into the script:

    – local Drives: Capacity, Used, Free Space

    – Mount Points: our DBs are directly attached via SAN now, so again, MountPoint Name, Capacity, Used, Free Space

    – DB statistics: DB Size, Number of Mailboxes, Mailbox Average Size, WhiteSpace in DB, Date of last FullBackup

    Paul, thanks a lot, I learned a lot, Rosario

    1. vikram

      how you did that how added drive size in the script

    2. Alex

      Rosario,

      Can you please give us the enhanced changes which you added ?

  330. Anant

    Hi,

    You can set forwarding on mailbox that is mentioned in the script.

    Just a workaround.

  331. coolguy

    Thanks for the script. however what is the parameter if want to send report to multiple recipients?

    1. Avatar photo
      Paul Cunningham

      You can set mutliple recipients in the SMTP config in the script separating them with a comma.

      To = “email1@domain.com”,”email2@domain.com”

      Or just put a single address that goes to a distribution list.

      1. Marcus

        Paul,
        I’ve tried what you’ve suggested and that does not work for me, it only sends to the first email address. Could you help out?

        Thanks

        1. Marcus

          Paul,
          Please ignore my previous comment, I was been a complete idiot, I found the problem.

  332. Kevin O'Brien

    Love this script. Thanks Paul!

  333. Pradeep

    Hi Paul,

    thank you for the great script.

    I am facing a strange issue here. When I run the script , no matter if i use server, server list or no parameter at all…. After displaying status of servers in my site, it automatically starts checking the servers in a remote site, which I obviously dont want to do. Could you please let me know what could be triggering this?

    Also, I used ignorelist parameter as well . but it didnt work.

    This is causing my script to pause for good 5 mins before displaying error that cannot connect to those servers.

    Any help would be much appreciated. Thanks

  334. sajeev

    Hi Paul,
    the script working fine. I’m trying to run this script in my task scheduler with a service account which have minimum priviliage on the server. For example, i want the service account able to complete the test and send the report out but unable to make any changes to Exchange or server and reboot/shutdown server. Do you have any suggestion on which kind of membership I should give to the service account ?

    1. sajeev

      Hi Paul,
      Any suggestion on the rights?

  335. James A. Peter

    Hi Paul,

    Any news on uptime check issue?

    Regards,

    JP

  336. Rhys

    Heya Paul,
    thanks for the script – nice work.

    Just one issue. I’ve had v1.1 working fine and have now upgraded to v1.2. Strangely enough I’m wrestling with permissions issues now. I am running with a domain service account which has “log on as a batch job” to the local server. However it refuses to run unless I make it a local Administrator of the machine. The task does not error, it just runs perpetually.

    If I remove the following line, it works (but then does not report on any DAG checks):
    . $env:ExchangeInstallPathbinRemoteExchange.ps1

    Any suggestions? (Exchange 2010)

    Cheers,
    Rhys

    1. Avatar photo
      Paul Cunningham

      I’ve noticed the same issue myself but haven’t had a chance to look into it yet.

  337. Anant

    Hi Paul,

    Thank you for the script. It is working fine.
    I just wanted to add two more colums LatestFullBackupTime and LatestIncrementalBackupTime

    I tried hard but no luck.(I dont have much idea about scripting)

    Could you please suggest

    Thanks in advance

    Anant

      1. Anant

        Thanks.

  338. Sushant

    Hi Paul,

    Currently we are running same script to export health of our exchange servers, Script is working ok..

    thanks for nice work.

    But My question is that can we exclude Database name instead of server name.?

    I am just checking if you have any alternate way to do this please help me.

    Thanks,
    Sushant

  339. Hayley Heskiel

    Hi! First I’d like to say this script looks fantastic and I’d love to get it running. Can this script work in a Exchange 2007 only environment?

    We have a CCR and 2 HT/CAS/MBX servers, and another CAS
    When I attempt to run it, I get the following:

    —— Checking EXCHE
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 352
    Server version: Exchange 2007
    Roles: Mailbox, Client Access, HubTransport

    Then it pauses there for a moment and the window just closes. This happens in Powershell, Exchange Management Shell, or Powershell Editor. I can’t seem to find why it’s closing and if it’s an error in the script or something else. Any help would be greatly appreciated.

    Thank you!

    1. Hayley Heskiel

      As an added note, it completely shuts down during the General Server Health Check.

    2. Sanjeev

      Hello Hayley,
      Wooten mentioned

      “Figured I would reply so others could fix it in 2007. I got it working using the following old script on 2007, just change the 2010 plugin to the 2007 plugin, comment out the 2010 Get-AD stuff, and add-in your smtp settings and you’re done.

      http://dl.dropboxusercontent.com/u/13009245/facility.net/Test-ExchangeServerHealth.ps1

      Also if anyone wants to setup scheduled task for this I got it working as well by created a batch file with the following code:

      powershell.exe -command “. C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

      btw, We are working to add “Test-OWAConnectivity” and ‘Test-Activesyncconnectivity” tests as well to the script for Exchange 2007. I’ll share it once completed.

      1. Hayley Heskiel

        Hi Sanjeev,

        I figured out the exact area that was causing that issue. I’d already changed the snapping to be for 2007. The section that runs the ping check apparently crashes the script. I don’t know why, but as soon as I removed the section, the script ran flawlessly. I left in the part about new object and the write host for a pass. This way it just registers the ping as a pass and moves on. If the servers aren’t pinging, I’ll know about it before then. It has to be in the script or the report ends up being skewed. Thank you for your help!

  340. Ziemek Borowski

    Hi,
    First – thank for that script. Extremly usefull. 🙂

    When I call that script from another (to get any “documentation snapshot” of env) I receive something like that:
    —- Database Copy Health Summary —-
    out-lineoutput : The object of type “Microsoft.PowerShell.Commands.Internal.Format.FormatStartData” is not valid or not in the correct sequence. This is likely caused by a user-sp
    ecified “format-table” command which is conflicting with the default formatting.
    + CategoryInfo : InvalidData: (:) [out-lineoutput], InvalidOperationException
    + FullyQualifiedErrorId : ConsoleLineOutputOutOfSequencePacket,Microsoft.PowerShell.Commands.OutLineOutputCommand

    In script before call Test-ExchangeServerHealth.ps1 I’ve only mkdir $repdir.
    Have You any idea how to fix it?
    Temporary workaourd (which works) is call Test-ExchangeServerHealth.ps1 into variable (also call mkdir into variable works). Or modify 6 lines starting from $dagdatabasesummary | ft (ie. by remove ft or comment that output — which is aceptable if we execute it for HTML/mail report).

    But it’s quite annoying. 🙂

    1. Avatar photo
      Paul Cunningham

      Yes, those 6 lines you refer to make the script a bit awkward for what you’re trying to do I’d say. Removing them is fine if you just want the HTML output.

  341. Sergey

    Hi,

    Nice script!!
    But could you please clarify what does mean status:
    – Mailbox Server Role required services not running.
    – Client Access Server Role required services not running.
    – Hub Transport Server Role required services not running.
    For one of the node in DAG cluster. Cluster is up and running. What should I check in this case?

    Thank you!

    1. Avatar photo
      Paul Cunningham

      Use Test-ServiceHealth to identify which service isn’t running.

  342. bounce813

    Paul, Your script is an amazing tool. I would like to send a copy of the HTML report to Share Point instead of the default location. Could you tell me where to set an alternate directory?

    Thank you!

  343. Paul Sathya

    Hi,
    The scripts run’s successfully but does not generate any report…

    1. Paul Sathya

      got it.

  344. Tony Holdgate

    We had an issue last night where our deployment scripts failed to set the http redirect for OWA for some new CAS servers we built. Is there a way to build this into the next version?
    CHeers
    Tony

    1. Avatar photo
      Paul Cunningham

      I have no plans at this stage to add anything that *changes* configurations.

  345. Kerry Denten

    G’day Paul,

    In the earlier versions of this script, it didn’t seem to cope well if it had been run more than once within a short amount of time.

    With that in mind, can this new version of the script be run at the exact same time on two separate nodes?

    Y’see, we have the script in place and fully configured to run on two of our HUB nodes, so that if one has a Transport failure, at least we’re still able to get reports and/or alerts from an alternative node with accurate health information.

    What I want to do is set up the “alerts” version of the script to run to the exact same schedule on two nodes every ten minutes.

    Then I want the “health report ” version to run to a staggered schedule across both nodes, thus delivering health reports every three hours from a different node each time.

    But what I don’t want to do is lull myself into a sense of false security thinking the alert scripts are happliy running every ten minutes, when in fact they’re failing, because I’m trying to run them simultaneously.

    I’ve run some tests, and the scripts seems to be coping with running simultaneously on two nodes, but I just thought it wise to check.

    Kerry

    1. Avatar photo
      Paul Cunningham

      I can’t think of any reason why it would not work if two servers were running the check simultaneously or within a short period of time.

  346. Clint Swiney

    Paul! AWESOME script made even better. You ROCK!

    We have a Lagged DAG in a separate Data Center which was causing failures when performing the Test-ReplicationHealth check, specifically the DBLogReplayKeepingUp health check. In order to repair I created a new variable:

    $transientevsupptimeout = 5 #Change to set the TransientEventSuppressionWindow in minutes for test-replicationhealth

    Then modified line (876 in the original script):

    $replicationhealth = $dagmember | Invoke-Command {Test-ReplicationHealth -TransientEventSuppressionWindow $transientevsupptimeout}

    This reduces the number of failures due to transient load generation.

    http://technet.microsoft.com/en-us/library/bb691314(v=exchg.141).aspx

    Now the script runs error free.

  347. Jeff St. Louis

    Figured it out… Both the command prompt (cmd.exe) and the Task Scheduler do NOT like the quotes around the command.

    powershell.exe -command E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail

    Strip them off, and voila. It’s working!

    Thank-you for your help

  348. Jeff St. Louis

    Hi Again,

    Just triple checked.

    If I run the following command in the command prompt (cmd.exe) it does not work and throws the error I posted earlier.

    If I run it from the powershell (fresh, just open and run) it works like it should.

    powershell.exe -command “E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail”

    It doesn’t like the “sendemail” parameter for some reason

  349. Jeff St. Louis

    Here’s what I get when i run it from the command line!

    C:Usersexchadmin>powershell.exe -command “E:PowerShellScriptsExchangeServerH
    ealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail”
    E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 : A par
    ameter cannot be found that matches parameter name ‘sendemail”‘.
    At line:1 char:96
    + E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -repo
    rtmode -sendemail” <<<<
    + CategoryInfo : InvalidArgument: (:) [Test-ExchangeServerHealth.
    ps1], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Test-ExchangeServerHealth
    .ps1

    1. Jeff St. Louis

      but if i open the powershell itself, navigate to the path and run the command it works great. hmmmm

  350. Jeff St. Louis

    Hi Paul,

    First things first, just wanted to let you know this is a great little script.

    I am having a small issue, I cannot seem to run the script using the Task Scheduler. It appears to run fine (no errors) but the html report doesn’t generate and I don’t receive an email.

    When I run it from the command line, it works great every time. The report gets generated and I receive a nice email.

    I’ve followed your instructions, plus I’ve adjusted the arguments and called the full path of the powershell command itself, but still no go.

    Have you heard of anybody else having this trouble, or am I the lucky one? Windows Server 2008R2 Enterprise, with Exchange 2010 SP3.

    Any tips or insight would be much appreciated! Thanks

    1. Shane Bryan

      Hi Jeff, I have it working in my environment via Task Scheduler. If you want to compare task settings maybe I can help.

      1. Shane Bryan

        For the record my settings are;

        General tab: run logged in or not, with highest privileges. Configure for 2008R2.
        Triggers tab: irrelevant, whatever schedule you want.
        Actions: Start a program: powershell.exe

        the command I have appended to it is;

        -command “. ‘C:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1’; Connect-ExchangeServer -auto; c:PsscriptsGet-MailboxReport.ps1 -all”

        The remaining tabs, conditions, settings & history shouldn’t impact on it, but I also have the option to allow it to be ran on demand.

        if you want a screengrab, please let me know. obviously i’ve made the changes in the script where needed for mail server etc etc.

        Cheers, Shane.

        1. Shane Bryan

          ahh sorry, wrong script. here’s the command i’m using.

          Actions – start a program – powershell.exe

          -command “. ‘C:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1’; Connect-ExchangeServer -auto; c:PsscriptsGet-DAGHealth.ps1 -detailed -sendemail”

        2. Avatar photo
          Paul Cunningham

          The latest version doesn’t need all that in the command. The settings I use are in the blog post above the bug list/FAQ bit at the end.

          Jeff, I’d suggest testing your Task Scheduler command in a cmd.exe window. See if that shows any errors (which will be a clue) or if it works fine (which will indicate that something in Task Scheduler is not right).

        3. Jeff St. Louis

          Giving it a try. Will let you know. Thanks for the post.

  351. Tony Holdgate

    HI Paul,
    We have 5 edge servers that I need to include for testing. I note in the script you say
    “If you want to include then, remove this If.”

    Being nowhere close to your skill level could you qualify the line numbers to remove? 409-423?

    Finally it would be great if there was a disk space check in there but that a nice to have only
    Thanks
    Tony

    1. Avatar photo
      Paul Cunningham

      Thanks for the suggestions. Since Edge is apparently here to stay in 2013 I have it on my list to add in some checks for that role.

      I agree, disk space would be handy as well. Its on the list.

      1. Tony Holdgate

        HI Paul,
        One more thing- Public Folder databases and replicas check? Might be a tough one. I know you test the services but is anything more possible?

        1. Avatar photo
          Paul Cunningham

          What specifically about public folder replicas?

          Keep in mind that the way Exchange 2013 implements public folders means that is all changing anyway.

        2. Tony Holdgate

          Specifically I’d like to test that the pf dbs are healthy and the replication is working.

    1. Avatar photo
      Paul Cunningham

      Yes, disk space is something I am working on including in future.

      1. ExchangeRocks

        Any update on the disk space piece on mentioned you were working on?

  352. Wooten

    Paul, I can’t seem to get this working in Exchange 2007, I have modified it to use the correct 2007 powershell plugin, and setup smtp settings correctly. However, when I run the script it gets past checking server roles, then closes the powershell window (crashes) with no errors that I see.

    1. Sanjeev

      I am also facing the same problem in Exchange 2007 environment. Looking at previous comment from the people regarding Exchange 2007, it seems the older version of the script works fine for Exchange 2007.

      Paul, Can we have the older version of this script? 🙂

      1. Wooten

        Figured I would reply so others could fix it in 2007. I got it working using the following old script on 2007, just change the 2010 plugin to the 2007 plugin, comment out the 2010 Get-AD stuff, and add-in your smtp settings and you’re done.

        http://dl.dropboxusercontent.com/u/13009245/facility.net/Test-ExchangeServerHealth.ps1

        Also if anyone wants to setup scheduled task for this I got it working as well by created a batch file with the following code:

        powershell.exe -command “. C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

        1. Sanjeev

          Thanks Wooten. That worked for me 🙂 . Just want to check if this test runs HT Services and Transport queue for Edge Server as well. Or As Edge server is in DMZ, Do we need to open some ports to make this work?

  353. Flo

    Paul,

    regarding “Healthy Queues” in the script, i can’t not really figure out, what that should mean. (and I also get a warning with a “2” in the field)
    Can you explain the test in a few words?

    Thanks

    1. Avatar photo
      Paul Cunningham

      Each database copy has a copy/replay queue for replication. An unhealth queue is one that has more logs in the copy/replay queues than the $replqueuewarning is set to (which I set to 8, but you can adjust it higher if you want to).

      Healthy Queues will be yellow (warning) if the number of healthy queues is less than the total number of queues.

      In other words, if you’ve got 3 copies of a database, and all three copies have healthy queues, then “Health Queues” will be green. If only two of the copies have health queues, then “Healthy Queues” will be yellow.

  354. Philipp Rusch

    Hi Paul,
    I am using your script on a fresh Exchange 2010 Server and cannot get the serverroles-checks to work.
    I always get something like “invalid argument, because it is NULL”, when binding parameter $serverinfoservices to -Name. Sorry that I can’t be more specific since I have the german version and have to translate this back to english

    1. Avatar photo
      Paul Cunningham

      The script still has some issues with non-English languages that I haven’t gotten around to fixing.

      Go to line 495 in the script and adjust the server role names there to your language and see if that fixes it.

    2. Rene Joram

      Hi Philipp,
      I already mentioned the changes, you must make to make this script running in german environments:

      To all who want to use this script with different language-Exchange-Servers:

      Regarding the errors on Exchange-Server in other languages:

      You have to change the lines 346-349, where there are only the english server-role-names.
      In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
      “Hub-Transport-Serverrolle Services: Pass
      Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

      So you must change (or add lines) e.g. on german exchange-server:

      “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
      “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
      “Mailbox-Serverrolle” { $roleservices = “MB Services” }
      “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

      instead of(or additional to):
      “Client Access Server Role” { $roleservices = “CA Services” }
      “Hub Transport Server Role” { $roleservices = “HT Services” }
      “Mailbox Server Role” { $roleservices = “MB Services” }
      “Unified Messaging Server Role” { $roleservices = “UM Services” }

      Additionally you must change the following line:
      if ($testmailflowresult -eq “Success”)

      to your own language, e.g. on german Exchange Server:
      if ($testmailflowresult -eq “Erfolgreich”).

      You can find the correct word of your language also in the output before you have fixed it:

      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test: Erfolgreich

      After these changes the script works fine for my german exchange organisation

    3. Rene Joram

      Update because of newer Version of Script:
      I have added/changed the following line on a german Exchange Server:

      Line 446:
      I added 4 lines:
      “Clientzugriff-Serverrolle” { $serverinfoservices = “Client Access Server Role Services” }
      “Hub-Transport-Serverrolle” { $serverinfoservices = “Hub Transport Server Role Services” }
      “Mailbox-Serverrolle” { $serverinfoservices = “Mailbox Server Role Services” }
      “Unified-Messaging-Serverrolle” { $serverinfoservices = “Unified Messaging Server Role Services” }

      After that I changes line 604 to:
      if (($mapiresult -ne “Success”) -and ($mapiresult -ne “Erfolgreich”))

      and I changed line 651 to:
      if (($testmailflowresult -eq “Success”) -or ($testmailflowresult -eq “Erfolgreich”))

      I don’t have DAG in my environments, could anyone, who has DAG and german (or other not-english exchange-server) please test, what happens with the DAG-Check?

  355. jeevan

    is there any script for performance metrics for exchange server

    -jeevan

  356. Michael Roth

    Paul,

    Thanks for the updated server health check script! We greatly appreciate the freebies you provide to help us monitor Exchange. 🙂

    I’ve tried to modify the script so that emails are only sent when there is an error or warning detected. In the process I noticed two variables called $alerts and $AlertsOnly. I tried to use the AlertsOnly as a switch as listed in line 139 but was unable to get it to work. I read through the comments section as well and noticed you mentioned adding the feature of only emailing if an issue was found. Suggestions?

    Thanks!! 🙂

    1. Avatar photo
      Paul Cunningham

      Looks like some code slipped in for the “Alerts Only” option that I haven’t finished fully implementing and testing yet. I have it on my list of improvements I’m working on.

  357. Sahin Boluk

    Hi Paul,

    Love your script. I used the previous version like a charm! Had it set on a schedule task and only e-mail if there was a failure.

    In the new version, not sure where to put the ‘Exit’ command so it doesn’t send an e-mail if there are no Server or DAG Health issues.

    Second, if there is a DAG issue, it doesn’t say that in the email. Says the following:

    Exchange Server Health Check Summary
    No Exchange server health alerts or warnings
    Exchange Server 2010/2007 Health

    Maybe add something after the “No Exchange Server Health Alerts or Warning” if there are any DAG issues so we can scroll down to take a look.

    Thanks again!

    1. Avatar photo
      Paul Cunningham

      Correct, that summary only refers to server health at the moment, not DAG health. I will be adding more summary details in the next version.

      But generally speaking I recommend people at least skim through the entire report looking for yellow/green rather than just rely on the summary 🙂

  358. kwannapa

    Hi Paul,

    I trying to run the script for send report to me. But it’s couldn’t send mail to me. I ran the scripts on the Hub Server and i change the smtp settings already. This is the results after ran the scripts is show below.

    —- Server Test-Replication Report —-

    Server ClusterServ ReplayServi ActiveManag TasksRpcLis TcpListener DagMembersU ClusterNetw QuorumGroup FileShareQu
    ice ce er tener p ork orum
    —— ———– ———– ———– ———– ———– ———– ———– ———– ———–
    MBXPN01 Passed Passed Passed Passed Passed Passed Passed Passed Passed
    MBXPR01
    MBXPR02 Passed Passed Passed Passed Passed Passed Passed Passed Passed

    —— Finishing
    Done.
    [PS] D:ScriptTest-ExchangeServerHealth>

    Thanks

    1. kwannapa

      and have this error :

      Windows Failover Clustering encountered a transient error. Trying the operation again may be successful. Error: ‘IsNod
      Clustered’.
      + CategoryInfo : NotSpecified: (0:Int32) [Test-ReplicationHealth], ExClusTransientException
      + FullyQualifiedErrorId : 33AD0105,Microsoft.Exchange.Monitoring.TestReplicationHealth

      Add-Member : Cannot bind argument to parameter ‘Name’ because it is null.
      At D:ScriptTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:880 char:47
      + $memberObj | Add-Member NoteProperty -Name <<<< $($healthitem.Check) -Value $($healthitem.Result)
      + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
      + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
      mmand

      Thanks a lot

      1. kwannapa

        [PS] D:ScriptTest-ExchangeServerHealth>.Test-ExchangeServerHealth.ps1

        This is command i ran it.

        Thank for your quickly answer

        1. Avatar photo
          Paul Cunningham

          Can you please review the instructions in the article again. They explain how to run the script to get an email report sent to you.

        2. kwannapa

          i set the schedule task that you recommend Arguments: -command “C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail” and then i click run this schedule task but i don’t received the mail report to me. Not sure why its don’t send mail to me. and i confirm that i change the smtp settings already.

        3. Avatar photo
          Paul Cunningham

          Try running it in your Exchange Management Shell:

          .Test-ExchangeServerHealth.ps1 -reportmode -sendemail

          That way you’ll see any errors that occur when the email is attempting to send.

          It is also worth double checking the email settings you’ve configured. Often people make a typo or miss a closing quote and it fails as a result. You should also make sure the server you’re running the script from is in the list of allowed IP addresses for the relay connector you’re pointing it at.

        4. kwannapa

          Thanks you very much Paul 😀

  359. Asif

    Thanks Paul. Grate script as usual.

    I remember in your previous script you had a column for backup as well, I don’t see in this script.

    Question: I am new to this Exchange 2010 and still struggling with many things.
    After I run this script I found error in Cluster Network (Failed). When I checked in DAGNetwork01 configuration it shows [subnets] 10.32.100.0/24 is Misconfigured, whereas DAGNetwork02 [Subnets] shows fe80::/64 Unknown.
    Any suggests how to fix it.
    Thanks

  360. Kerry Denten

    G’day Paul,

    Stellar work on this version of the health script. Works a treat with just a couple of tweaks to the batch file we use to run it.

    Would it be possible to stretch the friendship and ask if it’s possible to include storage usage, eg, available/used/overall per HDD or per LUN/array?

    Kerry

    1. Avatar photo
      Paul Cunningham

      I have been experimenting with that and the biggest challenge is accounting for all the different mixes of dedicated log/DB LUNs vs shared log and shared DB LUNs vs multiple databases on a single LUN and so on and so on, while still presenting the results in a useful way.

      Of course I love a challenge, so I will probably get it done some day, just not any time soon to be honest 🙂

  361. Shane Bryan

    Works perfectly, thanks Paul. awesome stuff that’s truly appreciated 🙂

    Cheers Shane.

  362. Avatar photo
    Paul Cunningham

    The script has been updated to v1.2, available at the same download link. This version includes several bug fixes and also adds the DAG health check.

    Please review the notes and instructions as some things have changed, eg the SMTP settings that you customize.

    Thanks everyone for your feedback and bug reports so far.

  363. Flo

    Paul,

    i’m still struggling to bring “test-owaconnectivity” and “test-activesyncconnectivity” to your script. Everything else is working flawless, but i got everytime a bunch of error messages by implement other cmdlets besides the existing ones.

    You have a hint to do that?

    Thanks, Flo

    1. Avatar photo
      Paul Cunningham

      I happen to be working on a script to run those CAS test cmdlets, and yes, they are a bit tricky to work into a script.

      1. Flo

        Yes, I’m trying to get them into the main script for two days now. Really tricky. I will continue to work on that, but maybe you are faster. 🙂

  364. Rene Joram

    To all who want to use this script with different language-Exchange-Servers:

    Regarding the errors on Exchange-Server in other languages:

    You have to change the lines 346-349, where there are only the english server-role-names.
    In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
    “Hub-Transport-Serverrolle Services: Pass
    Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

    So you must change (or add lines) e.g. on german exchange-server:

    “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
    “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
    “Mailbox-Serverrolle” { $roleservices = “MB Services” }
    “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

    instead of(or additional to):
    “Client Access Server Role” { $roleservices = “CA Services” }
    “Hub Transport Server Role” { $roleservices = “HT Services” }
    “Mailbox Server Role” { $roleservices = “MB Services” }
    “Unified Messaging Server Role” { $roleservices = “UM Services” }

    Additionally you must change the following line:
    if ($testmailflowresult -eq “Success”)

    to your own language, e.g. on german Exchange Server:
    if ($testmailflowresult -eq “Erfolgreich”).

    You can find the correct word of your language also in the output before you have fixed it:

    Public Folder databases mounted: Pass
    Mailbox databases mounted: Pass
    MAPI connectivity: Pass
    Mail flow test: Erfolgreich

    After these changes the script works fine for my german exchange organisation

  365. Skye

    Paul,

    Great stuff this script , we use it 24/7.
    Any word on when the new 1.2 version will be ready for download?
    Can’t wait!

  366. SREEJITH

    Hi Paul,

    Thanks for your script.

    I have a small issue. Please help me.

    I am supporting different clients with 2010 and 2007 exchange. I have implemented this script via task for exchange 2010 and working fine.

    But recently i did this for one of my 2007Box and i am getting the full result only if i manually run the script in exchange / windows powershell.

    if i run it via task i amnot getting the full details. after the summary the exchange health check details not showing. Please see the below sample report

    Exchange Server Health Check Report
    Generated: 04/02/2013 21:28:05
    Exchange Server Health Check Summary
    No Exchange server health alerts or warnings.

    Note: If i run the script directly from shell, i am getting all the results.

    Please help me..

    Thank You
    Sreejith

    1. Avatar photo
      Paul Cunningham

      The script is written to work with Exchange 2010. I suspect what you will need to do is replace the section early in the script that calls the Exchange 2010 snapin with the name of the Exchange 2007 snapin instead.

      1. SREEJITH

        Thanks Paul.

        I will try that.

        But i got fixed this by running a batch file. the content of the btch file is

        Cd “D:Program FilesMicrosoftExchange ServerBin”
        C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -psconsolefile “D:Program FilesMicrosoftExchange ServerBinexshell.psc1” -command “”

        Thank You
        Sreejith

  367. Chris

    Paul,

    How can i get the script to report the queue length as a number, instead of Pass/Fail in the email report?

    1. Avatar photo
      Paul Cunningham

      My current version lists the queue count next to the pass/fail result. Not sure if that is in the publicly released on yet though, but it will be in the next version I release.

  368. Lee

    Paul,

    Love the script, have used it for 6 months or so and it really helps me have a quick look to identify any issues that I would normally have to log into each server and run checks manually.

    My only issue is that recently we have moved a couple of servers out of a DAG, but they are still in service because they have public folders that are in use, until we can move and decom. During the test, those servers warn (which I expect) during the mail flow test that “No mailbox databases”.

    However, once the checks continue on to other servers that DO have mailbox databases available, I continue to get the warning message. I’m not a programmer by any stretch, but is it possible that the result for that test doesn’t get re-initialized?

    Thanks for all you do in helping us admins survive!

    1. Avatar photo
      Paul Cunningham

      That is possible. In the version I’m working on right now I can’t see a bug that would cause that, so its possible I’ve already fixed that up. That version will be out soon I hope.

      1. Lee

        Thanks!

    2. Lee

      Paul,

      Just downloaded the new version, and ran it. It definitely fixed the issue with databases showing as not available. Thanks!

  369. Bhushan

    When I run script via Exchange powershell all roles services indicate as PASS with green color
    but
    When I run script via Task Scheduler all roles services indicate as Fail with red color.

    please help me on this.

    1. Avatar photo
      Paul Cunningham

      Is your scheduled task configured to run with highest privileges?

      1. Bhushan

        yes it is configured to run as domain Administrator

        1. Avatar photo
          Paul Cunningham

          I mean the scheduled task itself, there’s a tick box to run with highest privileges.

        2. Bhushan

          Thanks Very much paul,…… you are amazing…

          Running with highest privileges….. resolves the issue….

          Thanks for wonderful script…..

  370. Mike

    Paul,
    I have used the scripted and you did a very good job.
    However I do not want to run this script from any of the Exchange servers, because if this particular server fails, I will not get any report. So I thought it would be good idea to install it on separate server.

    What do I need to install on a separate Win 2008 R2 server to run the script with success? Do I need to install the Exchange System Management Tools or is it enough to have a PowerShell with some additional add-ins?
    Mike

      1. Mike

        Thx Stephen – nice article.
        I have tried that.
        I have open the Power Shell on the Win 2008 R2 computer, and run the following command to connect to the Exchange remotely:

        $s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://[exchange FQDN]/PowerShell/ -Authentication Kerberos

        Import-PSSession $s

        And I cannot get through one thing – I cannot get this command to work on the remote server which doesn’t have Exchange manangement tools installed.

        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

        This command is one of the first in the scipt written by Paul.
        Do you have any idea how to overcome it?

  371. Keith K.

    Another Great script!

    I have about 50 servers in my environment. Is there a way to have the script run the report by alphabetical server name? I have the servers hard-coded into the script alphabetically but it doesn’t seem to work.

    1. Avatar photo
      Paul Cunningham

      Look for this line:

      $tmpservers = @(Get-ExchangeServer | sort site,name)

      You can change that to sort by just name if you like.

  372. Bill Michaels

    Hey Paul,

    I am using PS 3.0 and the send mail feature has changed it should be send-mailmessage.

    I can’t figure out what all to change in your script for me to get an email sent

    any help would greatly be appreciated

    Thanks Bill

    1. Bill Michaels

      Hey Paul,

      I fixed the email problem. I did notice another issue…The report is not giving me any mail flow results???

      Any help would be appreciated
      Bill

      1. Avatar photo
        Paul Cunningham

        I haven’t tested any of this script with PS 3.0 so its possible you will see problems.

  373. Cathryn Donlon

    Paul

    Is there an updated version of the script yet? I have a July 2012 version still.

    Kind Regards

    Cathryn

    1. Avatar photo
      Paul Cunningham

      The latest version (same download link above) is from August 2012 and fixes a few bugs in that earlier version.

      A new version will be coming in the next few weeks I hope.

  374. Sushant Jadhav

    Hi Paul,

    Is it possible to run this script with SCOM 2012 server.?

  375. Kirill

    Helllo, thank you, but need some help.

    I getting this error

    Mailbox databases mounted: Pass
    Mail flow test: No active mailbox databases
    —— Checking RU-EXCH1
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 352
    Server version: Exchange 2010
    Roles: Mailbox
    Роль сервера почтовых ящиков Services: Pass
    Add-Member : argument parametr”Name”, value NULL.
    C:scriptsExchangeServerHealthTest-ExchangeServerHealth.ps1:358 знак:52
    + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
    -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
    mmand

    Mailbox databases mounted: Pass
    MAPI connectivity: Pass

    1. Avatar photo
      Paul Cunningham

      This is probably a problem due to non-English language and it is something I am trying to fix in the next version.

      1. Kirill

        ok thanks, that will be very helpful

    2. Kirill

      i am using russian version of Exchange 2010 and R2, maybe i need to resave ps1 in utf8 format or set encoding string somewhre?

    3. Rene Joram

      Regarding the errors on Exchange-Server in other languages:

      You have to change the lines 346-349, where there are only the english server-role-names.
      In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
      “Hub-Transport-Serverrolle Services: Pass
      Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

      So you must change (or add lines) e.g. on german exchange-server:

      “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
      “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
      “Mailbox-Serverrolle” { $roleservices = “MB Services” }
      “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

      instead of(or additional to):
      “Client Access Server Role” { $roleservices = “CA Services” }
      “Hub Transport Server Role” { $roleservices = “HT Services” }
      “Mailbox Server Role” { $roleservices = “MB Services” }
      “Unified Messaging Server Role” { $roleservices = “UM Services” }

      Additionally you must change the following line:
      if ($testmailflowresult -eq “Success”)

      to your own language, e.g. on german Exchange Server:
      if ($testmailflowresult -eq “Erfolgreich”).

      You can find the correct word of your language also in the output before you have fixed it:

      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test: Erfolgreich

      After these changes the script works fine for my german exchange organisation

  376. Tim

    Thank you so much for sharing this magnificent piece of work.
    You have obviously put a lot of effort into this, not just the script but also the commentary and how-to guides

    Thank you again

    P.S> I’m a big fan of your articles and have used many of them in the past. Keep up the good work !!!

  377. SREEJITH

    I tried this command with scheduled task. but it’s not happening. Please help me.

  378. SREEJITH

    Sorry… It’s already there…

  379. SREEJITH

    Thanks for this script.

    Need one help. how can i include DB mount status to this report ?

  380. Akash Phoenix

    Hi Paul,

    Great script!! Need some help in adding this script to Task Scheduler for a daily email report. I have added the option -reportmode $true -sendemail $true in the “Add Argument” section in Task Scheduler and powershell.exe “program/script” but it doesn’t work!!

    Kindly assist me!!

    Regards
    Akash

  381. Stephen

    I ended up tweaking the email section in the script so it would just go out my Outlook application.

    if ($sendemail)
    {

    $ol = New-Object -comObject Outlook.Application
    $mail = $ol.CreateItem(0)
    $Mail.Recipients.Add($smtpto)
    $Mail.Subject = $messageSubject
    $Mail.HTMLBody = $htmlreport

    $Mail.Send()
    }

    Very much waiting for the DAG health section.

    One additional question that I think has been asked already in the comment but I will ask again. We have two MX servers and one of them does not have any datastores active on it and I get the following warning on the passive DAG server.

    Mail flow test: WARNING: Exchange can’t perform the mail flow test because currently there are no mailbox databases on server *SEVERNAMETAKENOUT*.

    1. Avatar photo
      Paul Cunningham

      That warning is normal under those conditions. I think the new version I’m working on accounts for that scenario a bit better.

  382. Feroz

    I have Exchange 2013 installed on my lab and i try your script its showing me this error

    [PS] E:script>.Test-ExchangeServerHealth.ps1 -server ex
    Initializing…
    —— Checking EX
    DNS Check: Pass
    Server up: Exception calling “Send” with “1” argument(s): “An exception occurred during a Ping request.”
    At E:scriptTest-ExchangeServerHealth.ps1:248 char:4
    + $result = $ping.send($ip)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : PingException

    You cannot call a method on a null-valued expression.
    At E:scriptTest-ExchangeServerHealth.ps1:249 char:8
    + if ($result.status.ToString() -eq “Success”)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  383. TRAN XUAN QUANG

    when I run the script “Test-ExchangeServerHealth.ps1” it appear the message
    “Call was canceled by the message filter. (Exception from HRESULT: 0x80010002 (RPC_E_CALL_CANCELED))”

    I want to check time to replicate from DC site to DR site (Server name: DR-mailbox-03 to HQ-mailbox-03), I also to know time to connected two server.

  384. Sahin Boluk

    Hi,

    Is it possible to only get an e-mail if there is a failure? What I want to do is setup a task to run every 10 minutes or so, and only send an e-mail if something fails.

    1. Sahin Boluk

      Nevermind, I see a similar post and solution here.

  385. Ross

    The script file has been saved to the C:temp folder on our Exchange server.

    The following command is run in EMS version 2.0 on the Exchange server.

    [PS] C:temp>Test-ExchangeServerHealth.PS1 -server EXG

    Result as follows:

    [PS] C:temp>Test-ExchangeServerHealth.PS1 -server EXG
    The term ‘Test-ExchangeServerHealth.PS1’ is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:30
    + Test-ExchangeServerHealth.PS1 <<<

    Can anyone tell me why this is not working?

    1. Ross

      Helps if I actually extract the script files. Now I get this.

      [PS] C:temp>.Test-ExchangeServerHealth.PS1 -server HADEG
      File C:tempTest-ExchangeServerHealth.ps1 cannot be loaded. The file C:tempTest-ExchangeServerHealth.ps1 is not digi
      tally signed. The script will not execute on the system. Please see “get-help about_signing” for more details..
      At line:1 char:32
      + .Test-ExchangeServerHealth.PS1 <<<

      1. Ross

        I see. OK that’s it for today. I’ll try this next week.

        TO PERMIT SIGNED SCRIPTS TO RUN
        ——————————-
        When you start Windows PowerShell on a computer for the first time, the
        Restricted execution policy (the default) is likely to be in effect.

        The Restricted policy does not permit any scripts to run.

        To find the effective execution policy on your computer, type:

        get-executionpolicy

        To run unsigned scripts that you write on your local computer and signed
        scripts from other users, use the following command to change the execution
        policy on the computer to RemoteSigned:

        set-executionpolicy remotesigned

        For more information, see Set-ExecutionPolicy.

        RUNNING UNSIGNED SCRIPTS (REMOTESIGNED EXECUTION POLICY)
        — More —

      2. Rich

        I am getting the same error. Any idea what resolved this for you?

        1. Avatar photo
          Paul Cunningham

          The script isn’t signed. You’ll need to adjust your PowerShell execution policy to run it.

  386. PaulR

    This script has been a great help but we have noticed an oddity. We run the script in a scheduled task. The task calls a batch file with in turns calls the power shell script. Here is the oddity. when called by the scheduled task one of our exchange servers reports three failures, CA HT, and MB services. When I run the batch file myself, double clicking the batch file, the report shows no failures. The batch file is called using the same credentials. The only difference is a scheduled task is calling the batch file and not by a user clicking the the batch file.

    get-reports.bat

    Scheduled task reports failures.
    User double click reports no failures.

    any thought on this?

    Thanks,

    Paul

  387. Krishna

    Hi Paul,

    This very great work you did. It helped a lot for us.
    But this script failed to send the CA,HT services while running from scheduler.
    It is running fine from shell prompt, and it is not updating the .html file generated at c:scripts while run from scheduler.

    Thanks.

  388. Ed

    Thanks for this script.
    I have one issue that I hope you can answer.
    I have pointed the smtp to my smtp server but I still get the:
    Exception calling “Send” with “1” argument(s): “Failure sending mail.”
    At C:nttaSoftwareTest-ExchangeServerHealth1Test-ExchangeServerHealth.ps1:809 char:13
    + $smtp.Send <<<< ($message)
    Error.
    My SMTP server is configured to accept on port 587.
    Is the script attempting to send on port 25? How do we change this?

  389. David McKenna

    Hi Paul,

    I’m new to this, it works perfectly if I run it in EMS on 2007 but I cannot figure out how to call it from a batch file? Please can you assist?

    Thanks

  390. srinivas

    Exception calling “Send” with “1” argument(s): “Failure sending mail.”
    At C:ScriptTest-ExchangeServerHealth.ps1:808 char:13
    + $smtp.Send <<<< ($message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

  391. Chris Martinez

    Hi Paul,

    Great script. Thanks for sharing!

  392. Sahin

    Hi Paul,

    thanks for all your hard work! in you new version can it be set up to email a second address only if there is a critical issue?

  393. Zachary Loeber

    Any way you can change your parameters in the next release a little? I rewrote it a bit to be more flexible partially for selfish needs but still could be useful for others.

    Parameters section:

    param (
    [Parameter( Mandatory=$false)]
    [string]$server,

    [Parameter( Mandatory=$false)]
    [bool]$reportmode=$false,

    [Parameter( Mandatory=$false)]
    [string]$reportfile=”exchangeserverhealth.html”,

    [Parameter( Mandatory=$false)]
    [bool]$sendemail=$false,

    [Parameter(Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
    [Alias(‘SMTP Server’)]
    [String]$smtpServer = “localhost”,

    [Parameter(Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
    [Alias(‘Email Sender’)]
    [String]$smtpFrom = “healthcheck@localhost”,

    [Parameter(Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
    [Alias(‘Email Recipient’)]
    [String]$smtpTo = “you@somplace.com”
    )

    1. Avatar photo
      Paul Cunningham

      Yeah. Actually all my scripts suffer from some inflexibility when it comes to paramaters and such, relying on editable variables in the script code. I’ve got a priority goal as I update them all for Exchange 2013 to make them more flexible in that sense.

    1. Avatar photo
      Paul Cunningham

      Haven’t tested yours but it looks neat.

      I’ve nearly got my stuff ready. Its been a tough few months trying to find time to do the updates on this script 🙂

  394. Tom Major

    Hi Paul,

    The script looks great but I’m not a programmer nor do I have a lot of experience with a command line. Does the script add/modify anything on the server or in AD or make any changes when run? I too am interested in a DAG check as well.

    Thanks,
    Tom

  395. Scot Whiteley

    Hey Paul,

    Great Script. I like it.

    Please can you expand the exchange server version in your next script… For example: Exchange 2010 SP2, server build… blab blab…

    thanks,
    –Scot

  396. Tom

    Great script Paul.
    But i get a strange issue. If I run a script on EMS with reportmode and sendmail parameters (.Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true) – results as expected.

    Once I schedule a task to run script – all works thou results i get are not correct. I get CA,HT,MB service checks failing all the time on server i run task on.

    Those services are up, I also get Pass results if I run scripts from EMS.

    My Exchange setup is: 2x Exch Servers 2010 SP2 with Mailbox, ClientAccess, HubTransport Roles.
    Looking forward for your comments. Thanks.
    Tom

    1. Avatar photo
      Paul Cunningham

      Hi Tom, are your servers configured for a language other than English?

      1. Tom

        Hi Paul,
        Nope. Language is english.

      2. Tom

        Hi Paul,
        Not sure what was the issue but script works OK now. Deleted scheduded tasks, re-done, copied over script again. Issue fixed.
        Thanks.

  397. sajy2k

    Hi Paul,
    I wanted to run this script in my environment, but I need to include credential to send out email using the SMTP.. Is there anyway to use my credential with the script ?

  398. Paul

    Thanks you for the great script! I wanted to add the information that was output after the fail. In my case it looks like this.

    Public Folder databases mounted: Pass
    Mailbox databases mounted: Fail
    Offline databases:
    Mailbox Database DB6

    I’d like to include this in the report.

    Server Errors Warnings
    EXG-SVR2 Mailbox databases not mounted. MAPI tests failed. (currently blank) Mailbox Database DB6

    It would be nice to see what was causing the error in the email.

    How or where can i implement this in the script. I am new to power shell but I do have programming experience.

    Thanks again for this great script!

    Paul

    1. Avatar photo
      Paul Cunningham

      A very early version of the script actually did do that but I took it out because (a) the code itself was pretty messy, and (b) it made a terrible mess of the HTML report/email when a server had a bunch of different things wrong with it (eg if the Information Store is down, you get that plus all the DB’s offline plus all the failed MAPI tests so it becomes a big mess in the report).

      1. Paul

        Thanks for the note and quick response.

        Paul

  399. Nick

    Thanks Paul, excellent script, my only problem is that I have not yet received the HTML report via email 🙂

    I have set the smtp info as per above for our environment

    1. Nick

      never mind its running 100%, mail flow was a bit slow thru our smart host

  400. Fredrik Engman

    Nice script, looking forward to the DAG checks.

  401. James Mc

    First, I wanted to say what a great report this is, very helpful tool.

    Second, the reason I found this was my search for copy status health checks. Were you able to make any progress on adding that back in?

    Thanks for the great tool
    James Mc

  402. Oleg A

    Thank you very much for great script.

    My little troubleshooting about this error, that some got:
    Cannot convert value “1 301” to type “System.Int32”. Error: “Input string was not in a correct format.”

    You using this statement to format total hours: [int]$uptime = “{0:N0}” -f $uptime

    So because of Russian locale on my servers I have ” ” (space) as Digit grouping symbol.
    That’s why we got “1 301” in result that cose error to convert into integer value.

    So I just replace one simbol (N to D): [int]$uptime = “{0:D0}” -f $uptime
    And now have no error with this.

    Hope this help.

    PS. In fact I found days in this parameter more helpful, so I change to this:
    [int]$uptime = (New-TimeSpan $laststart $now).TotalDays
    [int]$uptime = “{0:D0}” -f $uptime
    and
    “Uptime (hrs)” to “Uptime (days)”

    Thank you again.

    Waiting for new version of script!

    Best regards,
    Oleg A.

  403. amit

    i wanted to use for exchange 2007 in production environment so can you pls help me how can i alter the same and use with exchange 2007.

    What i observed that when i am running the script i am getting the below error but seems to be it is going through. So what change I can do if wann use with exchange 2007 or can I ignore get-ADserver Settings error as I know this is because of exchange 2010, so if I can ignore the error or change something in script to use with exchange 2007. PLs help.. Thanks
    [PS] C:\>.Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true
    Initializing…
    The term ‘Get-ADServerSettings’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
    path was included, verify that the path is correct and try again.
    At C:Test-ExchangeServerHealth.ps1:83 char:27
    + if (!(Get-ADServerSettings <<<< ).ViewEntireForest)
    + CategoryInfo : ObjectNotFound: (Get-ADServerSettings:String) []
    , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    —— Checking CASHUB
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 0
    Server version: Exchange 2007
    Roles: ClientAccess, HubTransport
    Client Access Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 1
    —— Checking MBX
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 0
    Server version: Exchange 2007
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Mailbox databases mounted: Pass
    Mail flow test: Success

    1. Avatar photo
      Paul Cunningham

      Get-ADServerSettings is an Exchange 2010 cmdlet.

      If you’ve got Exchange 2007 and only a single domain in the forest then just commend that part of the script out.

  404. Sam O'Donnell

    Hi Paul,

    love this script, used at a couple of individual sites and works like a charm! are you planning on implementing DAG and Database Copy status into the script?

    Regards

    Sam

  405. Paul L

    Hi Paul,

    This script is great and i’ve been using it for a while. However I’m getting a false failure on one server for HT services. Tranport and mailflow both are fine. If I check services, all are fine and the server is fully working. Any idea what would cause the false positive?

    thanks
    Paul

    1. Avatar photo
      Paul Cunningham

      On the server in question run Test-ServiceHealth and it will tell you which service is not running.

  406. Hemant M.

    Hi,
    Paul, its a great script..I have run it in my organization with a success. I want to patch to more options in this script i.e. Disk space alerts and backup alerts.
    how i can go about that.

    Thanks
    Hemant M.

  407. Antonio Roura

    Hi Paul I am running this command as explained in the video .test-exchangeserverhealth.ps1 -reportmode $true -sendemail $true

    and throws me the following error

    File C:UsersarouradesktopTest-ExchangeServerHealth.ps1 cannot be loaded. The file C:UsersarouradesktopTest-Ex
    angeServerHealth.ps1 is not digitally signed. The script will not execute on the system. Please see “get-help about_s
    ning” for more details..
    At line:1 char:32
    + .Test-ExchangeServerHealth.ps1 <<<<
    + CategoryInfo : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

    that could be?? says something of a digital signature

    thanks for your help.
    regards
    Antonio Roura.

  408. Pavel Nagaev

    Paul, thank you for script.

    I think it is better to include information about CPU loading and free space at hard drives.

    1. Bikram

      I second this request as this is a major concern… Hard Disk getting full and not aware of this can and has created havoc many times…

      Is there a way to add HDD consumption/ free/ space data into these reports.

      Thanks for such awesome efforts & script… gives insight and foresight of exchange environment

      Thanks,

  409. Fredo

    Good morning Paul,

    I was wondering if it would be possible to add to your AWESOME script, a health check of all the “Content Index Catalog”?

    Much appreciated sir 🙂

      1. abby

        sooo excited for the updated version! 😉

  410. Elio @TW

    Excellent script, thanks very much.

    One small change I made was to edit line 356 from:
    $false {$svchealth = “Fail”; Write-Host -ForegroundColor $fail “Fail”; $serverObj | Add-Member NoteProperty -Name “Error Details” -Value ($($serverObj.”Error Details”) + $string5) -Force }
    to:
    $false {$svchealth = “Fail”; Write-Host -ForegroundColor $fail “Fail”; $serverObj | Add-Member NoteProperty -Name “Error Details” -Value ($($serverObj.”Error Details”) + $string5 + $s.ServicesNotRunning) -Force }

    Adds the detail from Test-ServiceHealth failure to the Error Details table.

  411. Zachary Loeber

    Hey Paul,

    Thanks again for being a rock star. I integrated your script into my own as best as I could. If you see any areas of improvement or don’t like my describing your health report as “kick-ass” please let me know and I’ll do my best to fix things up.

    http://gallery.technet.microsoft.com/scriptcenter/Troubleshoot-Exchange-2010-aecdc23f

    The only item I was tempted to change was adding an option to spit out the html report as a returned value and adding a silent mode so I could more easily wrap code around it.. That is not really a feature request though as I’m guessing only a small majority of people using your script are needing that kind of thing (only weirdo fellow scripters like myself).

    Regards,
    Zach

  412. Zachary Loeber

    Hello Paul,

    I’m not certain how I missed this particular release of yours until today. Good job on the health test script! I’ve recently released something a bit like this but just for using the built in scripts that come with exchange 2010 (http://gallery.technet.microsoft.com/scriptcenter/Troubleshoot-Exchange-2010-aecdc23f). If I rolled in your script as an optional parameter (would set it up to call your script which others would need to manually download from your site to utilize probably) would you mind? Or maybe even the other way around?

    Cheers and thanks again for sharing with the community!

    1. Avatar photo
      Paul Cunningham

      Hi Zach, feel free to incorporate any of my scripts into your own however you wish, whether as an external dependency or by reusing code. If its something you’re publicly releasing a credit in your script help/comments would be appreciated 🙂

      1. Zachary Loeber

        Absolutely, I’d have it no other way good sir 😉 As you maintain your script I’ll just make it an external dependency. Updates forthcoming soon.

  413. Sahin Boluk

    Hi Paul,

    Great Script! Love it! One thing, is it possible to get the number of messages in the Queue in the e-mail report?

  414. Lee Hutchinson

    Great Script! Thanks Paul.

  415. Jason Hauck

    Thanks for the awesome script! I’m new to Powershell and 2010 but we just built out our 2010 servers with 4 Mail DB servers in a DAG. Any chance of incorporating something from Get-MailboxDatabaseCopyStatus into the script? I think you said that was coming in a future version, but just checking. It would be a helpful addition for us to know if we need to reseed or anything.

  416. abby

    Hi Paul,

    On the original script, content indexing is included. Is it possible to include it again? Thanks!

  417. Pradee Purohit

    Hi Paul,

    Thanks for your great work. I have 2 queries:

    1. Can we exclude PF databases to be checked? Incase I have PFs remotely over a WAN link?
    2. I am not able to restrict the script to run only on my current Site, it goes to different sites over WAN link and check every server which results in a lot of Red (which I hate to see :))..

    thank you in advance for your reply.

    Also, could you please suggest nice training material for Powershell for exchange?

  418. Alex

    Hi Paul,

    thanks for that great script. I have an proposal for the health check: We use the Outlook Web Access and Active Sync. Is it possible to include those tests too? That would be great because otherwise i have to check those services with a different script.
    Greets
    Alex

    1. Avatar photo
      Paul Cunningham

      Have added them to my notes as feature requests. We’ll see how it goes 🙂

  419. Sean

    Thanks Paul, great script!!

    Would be great to have this be installed to run at defineable intervals (e.g. every 5 minutes), but only email if the HTML output has materially changed due to a significant change in status (i.e. a server that was down is now up).

    Another idea would be to capture perf statistics (e.g. how many MAPI users are logged on, how many through OWA, etc.). This might be a whole other script or at least not activated by default.

    Tx
    –sc

    1. Avatar photo
      Paul Cunningham

      When this script was originally created I had two goals:

      1) Do a real time, quick health check of a server (eg someone says “Hey is email not working?” you can quickly run it and see whether any obvious issues are there.

      2) A daily health check report that I can check via my iPhone early in the morning to see if any issues have arisen overnight, before business hours begin.

      It never was, and probably never will be, intended to be used for continuous monitoring and alerting during the day. There are much better solutions for that, for example Andy has a series of articles on using Nagios for monitoring Exchange:
      http://www.telnetport25.com/2012/01/installing-nagios-on-ubuntu-server-11-10-then-monitoring-windows-and-exchange-serverspart-1configuring-ubuntu-for-the-installation-of-nagios-core/

      But, the script code is freely released to the public for anyone to use and adapt as they see fit. So you might take it on board as something you develop further, by all means do 🙂

  420. Avatar photo
    Paul Cunningham

    I’ve just uploaded v1.1 which has just a few minor bug fixes in it. I’ve also added a bug list/FAQ section to the end of the article to let everyone know which issues I’m working on.

    1. Cam McDonald

      Thanks for all the work
      Were do I download newest file (must be blind lol)
      Thanks Again

      1. Avatar photo
        Paul Cunningham

        Same download link as before, in the article. I update the file on the back end.

        1. Cam McDonald

          Wow Thanks for the speedy Reply Have a good day

  421. Henry

    So… I guess an obvious but silly question… I have it set up. And it is working AMAZING. But… if there is a disruption in mailflow for whatever reason… will it still be able to send the email message? LOL. I used the “EXIT” command to stop it if there is not a problem. So… if there is a problem, and it sends the email message, will it still be able to send it? If that makes sense…

    1. Avatar photo
      Paul Cunningham

      Valid point. If there is a critical mail flow issue in your environment then of course the report email will also likely not be delivered.

      But the HTML report file that is generated can be used instead in those cases. So if you direct that file to a specific location using the -reportfile parameter, and are running IIS, you can open the HTML report via your web browser (even have it as one of your home tabs for the start of the work day).

  422. Jake

    Paul,,, When it gets to mail flow test I just get the following – *FAILURE*
    Any ideas?

    1. Avatar photo
      Paul Cunningham

      Mail flow tests are failing 😉

      Next version is going to use a simpler mail flow test (that is also slightly less thorough) to avoid some bugs that are cropping up.

      1. Carlos

        Hi Paul,

        Many thanks – your script is a life-saver!!
        However, I am having similar issues with the Mail Flow Test.
        We have an Exchange 2013 environment. I am running the script in a scheduled task with the argument below:
        Powershell -executionpolicy bypass -file C:1ScriptTest-ExchangeServerHealthSW.ps1 -Log -SendEmail

        The report that gets mailed always shows that “mail flow test failed” on both my exchange servers. If I directly run the same command in Powershell or via Start > Run, I get a Pass for all the tests.

        I had a look at the Log generated, and the one line in there says “11/30/2015 13:45:03 The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
        11/30/2015 13:45:03 Mail flow status is Fail”

        Please help when you can, I have no clue what’s going on.
        Thank you,

        1. Avatar photo
          Paul Cunningham

          Might be just the PS remote session failing. I’d need to see the full log. You can email it to me at paul (at) this domain.

          1. Carlos

            Thanks Paul – I have now mailed you the log.

          2. Carlos

            Granting the service account “Server Management” permissions solved my issue. Many many thanks Paul!! 🙂

  423. LeeH

    Paul,
    First of all, thank you for the script. I found an error condition that involves my Edge Transport Server. I run the script from my Exchange server that has the Mailbox, ClientAccess, and HubTransport roles. Next the script queries my EdgeTransport server. Since the EdgeTransport sits in my DMZ and is not actually in my domain, for it I get:
    DNS Check: Pass
    Server Up: Pass
    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)
    Uptime (hrs): Unable to retrieve uptime
    Server version: Exchange 2010
    Roles: Edge

    I know why it does that, but like I said, thanks for the script.

    1. Avatar photo
      Paul Cunningham

      Next version is going to just exclude Edge Transports for the time being. Between firewalls and permission issues there is a lot to take into account for testing the Edge role.

  424. Shane Bryan

    Hi Paul. When I run the script (which is great thank you) I get an error, which I thought was because we have a number of passive servers, but I hope you can clarify.

    We have 5 servers in our Exchange setup accross 2 sites.

    Site 1. 1x Client Access, Hub Transport (both roles on one server) – XCAS01
    Site 1. 2x Mailbox servers – XEXDB01, XEXDB02

    Site 2. 1x Client Access, Hub Transport (both roles on one server) – BCAS01
    Site 2. 1x Mailbox server – BEXDB01

    Site 2 is a DR site.

    When I run this script and generate the email, the 2 CAS servers report a few services, including Mail Flow Test as n/a. The 3 Mailbox servers fail the Mail Flow test. At first I thought this was because we have passive servers, but not all 3 are passive.

    From in the Exchange Management Console, currently XEXDB02 has the mailboxes mounted. The other 2 report that the Copy Status is healthy.

    From this information it may not be possible to provide accurate advice, but any advice is appreciated as to if this is normal behaviour or not.

    Cheers, Shane.

    1. Avatar photo
      Paul Cunningham

      Hi Shane, I’ve got that one on my bugs list. Should be pretty simple to stamp out in the next version.

      1. Kerry Denten

        Hi Paul,

        That’s great to hear, because like Shane, we’ve been experiencing the exact same problem and have had to abandon using the script for the time being as it’s giving too many incorrect results, particularly as it relates to mailflow on MBX servers.

        Kerry

        1. Avatar photo
          Paul Cunningham

          Yep, stay tuned Kerry. Hoping to have an update out soon.

          This is the fun part, when the scripts get run outside of my limited test environments and the bug reports roll in 🙂

      2. Shane Bryan

        Ahh thanks Paul (and Kerry, glad to hear it’s not me being a doofus). I planned to schedule this in an email which is delivered to a mailbox that the Helpdesk team check.

        I may put that in place, but let them know not to be alarmed by the red error squares, then update things when the bug is ironed out 🙂

        Cheers, Shane.

        1. Kerry Denten

          I was thinking about doing a similar thing Shane, but I reckon it could lead to a bit of the “boy who cried wolf” syndrome.

          Y’know, the possibility that once the bug is ironed out, they pay no attention to an alert because they’ve seen so many already, that they ignore what ends up being a genuine problem?

          Kerry

        2. Shane Bryan

          Yep I’ve put it on hold until the bug is removed 🙂

          No point flooding the Helpdesk with information to ignore.

        3. Marc Kean

          The mail flow test fails for me too. I have two sites, with an active mailbox server on one site and a passive mailbox server on the other site.

  425. Hein Traag

    One other thing to ask before turning my attention elsewhere.. we also use a powershell script to check on the health of the databases. I am not much of a coding guru 🙁 and can’t figure out how to include the following into the html report:

    function Get-DatabaseStatistics {
    $Databases = Get-MailboxDatabase -Status
    foreach($Database in $Databases) {
    $DBSize = $Database.DatabaseSize
    $MBCount = @(Get-MailboxStatistics -Database $Database.Name).Count

    $MBAvg = Get-MailboxStatistics -Database $Database.Name |
    %{$_.TotalItemSize.value.ToMb()} |
    Measure-Object -Average

    New-Object PSObject -Property @{
    Server = $Database.Server.Name
    DatabaseName = $Database.Name
    LastFullBackup = $Database.LastFullBackup
    MailboxCount = $MBCount
    “DatabaseSize (GB)” = $DBSize.ToGB()
    “AverageMailboxSize (MB)” = $MBAvg.Average
    “WhiteSpace (MB)” = $Database.AvailableNewMailboxSpace.ToMb()
    }
    }
    }

    Get-DatabaseStatistics | Export-Csv c:windowstempreport.csv -Force -NoType

    Send-MailMessage -To *********@yourdomain -From *********@yourdomain -Subject “Mailbox Database Statistics for $((get-date).ToShortDateString())” -SmtpServer yoursmtpserver -Attachments c:windowstempreport.csv

    Can’t remember where i got the script so all kudos go to the original author whoever it may be. The report is exported to csv and then mailed but it would be really awesome to have the two scripts combined in a report html that displays the health of the mail servers and the databases they contain.

  426. Hein Traag

    Excellent script Paul. I am getting a nice report in my mailbox. I do have one error in the execution of the script. I get the following error in the shell:

    Cannot convert value “Unable to retrieve uptime” to type “System.Int32”. Error: “Input string was not in a correct form
    at.”
    At C:********ToolsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:683 char:19
    + $hours = [int] <<<< $($reportline."uptime (hrs)")
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

    What do i need to change in the script or my environment to make that part work? Running a Exchange 2010 DAG setup here.

  427. Vann

    Hi Paul,

    Mine works and does its thing but I can’t seem to get the report to be emailed to me.

    I’m running this directly on the exchange server.

    Here is the error I get.

    Exception calling “Send” with “1” argument(s): “Failure sending mail.”
    At C:scriptsTest-ExchangeServerHealth.ps1:795 char:13
    + $smtp.Send <<<< ($message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    1. Avatar photo
      Paul Cunningham

      That error indicates you haven’t updated the $smtpServer variable in the Email Settings section of the script with a valid entry for your network. Could you double check that please?

  428. Mohammed Abid

    I am getting error for Edge Server(DMZ) access denied.How to proceed further

  429. Nate-n8

    Thanks for sharing this script.

    I thought the DNS check was clever, but it didn’t report failed when it probably should have. This week we had 2 forward DNS records that got deleted and the System.Net.DNS check still reported it pass. I’m guessing once queried, its cached locally onto that machine? I ran ipconfig /flushdns which it properly failed after that. Any way to always directly query the DNS server or something else rather than having to run flushdns?

    Also, just curious if you have a reason or preference on using System.Net.NetworkInformation.Ping over cmdlet Test-Connection?

    Thanks again!

    1. Avatar photo
      Paul Cunningham

      Hi Nate, interesting scenario on that DNS check. I’ll see if there is a practical way to account for it.

      As for the ping method, when this script was originally born it was in PowerShell 1.0. Later when I tried to use Test-Connection I ran into a weird crashing issue further along in the script and traced it back to the use of Test-Connection.

      Some day I hope to get to the bottom of it, or maybe PS 3.0 will solve it for me 🙂

      1. Nate-n8

        Thanks, I ended up using the function forward_lookup from http://meanderingmarcus.wordpress.com/tag/dns/. I slightly revise to report either pass or fail. This worked perfectly for me. This will tell me if its not in DNS, or if it can’t query DNS (DNS server down).

  430. shc

    Hi Paul! great script! works great and quick! I have an issue emailing the report, I get the following error.

    Exception calling “Send” with “1” argument(s): “Failure sending mail.”
    At E:reportsscriptsTest-ExchangeServerHealth.ps1:796 char:13
    + $smtp.Send <<<< ($message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    I read the fix above but that didn't work, any ideas?

    1. shc

      Hi Paul, not sure if you missed this issue….

      1. Avatar photo
        Paul Cunningham

        I’ll look into it. Is there any other error details that is provides?

        Have you changed the script variables to point to a valid SMTP server?

        1. shc

          Yes, it is pointing to the correct smtp server now. Thanks Paul! that corrected it. I had it pointing to the mbx server.

    2. Jan Kovar

      Hello Paul.

      I have the same issue as previously mentioned. Single Exchange server 2010 SP1 RU6 running on Windows 2008 R2 SP1 in Hyper-V.

      [PS] D:scripts>.TestExchangeServerHealth.ps1 -reportmode:$true -sendemail:$true
      WARNING: Active Directory server settings remained unchanged.
      —— Checking SSTMAIL
      DNS Check: Pass
      Server up: Pass
      Uptime (hrs): 147
      Server version: Exchange 2010
      Roles: Mailbox, ClientAccess, HubTransport
      Mailbox Server Role Services: Pass
      Client Access Server Role Services: Pass
      Hub Transport Server Role Services: Pass
      Total Queue: 0
      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test to SSTMAIL Success
      Exception calling “Send” with “1” argument(s): “Failure sending mail.”
      At D:scriptsTestExchangeServerHealth.ps1:795 char:13
      + $smtp.Send <<<< ($message)
      + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : DotNetMethodException

      Thank you for pointing me out, where could be the error. The HTML report is generated. I can find it on the drive in the path where it should be.

      BR
      Jan

  431. Simon Craner

    I have managed to get my health report to work against only my servers and not the entire org.

    instead of using the array command against mailboxserver etc, use the get-exchangeserver command with the pipes to the required where clauses, such as:

    get-exchangeserver | where {$_.name -like “*thisismyserver*”} and so on. “*thisismyserver*” format is the naming convention that you would follow, i.e. you share org with company1 and you are company2, so therefore “*thisismyserver*” would look like this “*company2*”.

    Instead of using the array part again the dag, using where clauses again, targeting only your’s and it works.
    I still get some errors regarding the services not being able to be checked.

    Paul many thanks once again, also edited where the DAG details are and i am targeting only my dag and not all the others.
    Hope this help others.

  432. Marco

    Paul,
    when i run the script using SCHEDULE, i get ERRORS on the result email pointing that CA, HT and MB services are not running.

    However this errors are not present when I run the script from PS window, everything shows in GREEN (PASS).

    The schedule is setup using your instruction as given in SET-AUTOMATED-EXCHANGE….. tutorial.
    the action is set to:
    -command “c:scriptstest-exchangeserverhealthtest-exchangeserverhealth.ps1 -reportmode $true -sendemail $true”

    BRGDS
    Marco

    1. Marco

      Reposting same issue:
      Script running fine from PS command , everything shows in GREEN, but on the email message I get error:
      “Required services not running. Required services not running. Required services not running.”
      reffering to CA Services:Fail; HT Services:Fail; MB Services:Fail.

      What am I doing wrong?

      BRGDS
      Marco

        1. Marco

          No, EXCHANGE and the Server2008 are English.
          the local settings are Danish.

        2. Avatar photo
          Paul Cunningham

          Marco, could you send me an email to paul@practical365.com, if you don’t mind I’d like to test a few things with you to work out how to make the script work for systems in other languages.

      1. Fredrik Engman

        I’ve got the same problem, when i run the script from the shell CA and HT Services says Pass. When i schedule the same script it says Fail on CA and HT.

        I’m running English Windows 2008 and English Exchange 2010 but the locale on Windows is Swedish.

  433. Simon Craner

    using the ignorelist i get this error just after it check each one of my servers:

    Cannot convert value “1 422” to type “System.Int32”. Error: “Input string was not in a correct format.”
    At C:TempTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:261 char:18
    + [int]$uptime <<<< = "{0:N0}" -f $uptime
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

    1. Avatar photo
      Paul Cunningham

      Seems to be having trouble with the uptime calculation for some reason. I can try and reproduce the bug, but can you give me a clue how long its been since the last time your servers were restarted?

      1. Gavin Morrison

        Paul, I have seen this as well for the tests against edge servers that are either not on the domain or have restricted access through firewalls from the core network. As a result queries cannot be completed, although in the html report the uptime value seems to be being entered as the same as the previous server in the table due to the conversion error.

        1. Avatar photo
          Paul Cunningham

          I’ll try and fix that uptime value issue but for now its probably better just to add Edge servers to the ignorelist.txt

  434. Rafi

    Hi,

    Got it as “inheritance” guess i can just set it to be Auto and Running.

    Thanks.

  435. Rafi

    Hi,

    I see it’s because we don’t use Edge and script check for it’s service:
    Role : Hub Transport Server Role
    RequiredServicesRunning : False
    ServicesRunning : {IISAdmin, MSExchangeADTopology, MSExchangeServiceHost, MSExchangeTransport, MSExchangeTransp
    ortLogSearch, W3Svc, WinRM}
    ServicesNotRunning : {MSExchangeEdgeSync}

    Can we skip it?

    Thx.

    1. Avatar photo
      Paul Cunningham

      What is the status of the service? Have you set it to manual or disabled?

      My servers, even those not involved in EdgeSync, have it Automatic + Running at the moment.

      1. Rafi

        Disable

        1. Avatar photo
          Paul Cunningham

          Any particular reason? It can be Auto and Running even if there is no Edge servers. That will clear up that error with the Test-ServiceHealth part of the script.

  436. Rafi

    Hi, Great script, thanks a lot.

    My environment is EX2010&07, anyone has a clue why i get
    “Hub Transport Server Role Services: Fail” on all CASHUB servers.

    Regards,
    Rafi.

    1. Avatar photo
      Paul Cunningham

      Please run Test-ServiceHealth on one of those servers and paste the results here.

      1. Rafi

        Hi Paul, thanks, here it is, same for all HUB|CAS servers, services up and running.

        —— Checking xxxx
        DNS Check: Pass
        Server up: Pass
        Uptime (hrs): 572
        Server version: Exchange 2010
        Roles: ClientAccess, HubTransport
        Client Access Server Role Services: Pass
        Hub Transport Server Role Services: Fail
        Total Queue: 0

  437. Simon Craner

    after a little bit of fiddling i got it to work, but now get an error, not sure if this is due to my changes.

    below is the error from the shell:

    DNS Check: Pass
    Server up: Pass
    Cannot convert value “2 961” to type “System.Int32”. Error: “Input string was not in a correct format.”
    At C:TempTest-ExchangeServerHealth.ps1:261 char:18
    + [int]$uptime <<<< = "{0:N0}" -f $uptime
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

  438. Simon Craner

    Great script once again. Because my exchange environment sits in a shared org, i need to target my servers which have a specific naming convention. Which line etc would i put my “where” clause in?

    1. Avatar photo
      Paul Cunningham

      Stay tuned, I’m going to update it with some options for being more specific with the servers you test.

      1. Simon Craner

        I have also tried to change:

        $exchangeservers = “server1″,”server2” etc

        it still runs through all items in the org and not just check my servers.

        1. Avatar photo
          Paul Cunningham

          Perhaps you’ve changed the wrong line. If this was the line you changed…

          $exchangeservers = Get-ExchangeServer $server -ErrorAction Stop

          …that is not the correct one. The script was written with your scenario in mind so suggesting a code change here in the comments is getting a bit tricky in this case.

          I’ll update the script this week with the option to specify a file containing a list of servers to check, but in the meantime I’d suggest just using the ignorelist.txt file to exclude the ones you don’t want to check.

          1. Matt D

            Hi Paul – I’m after something similar with the opposite of the ignore list – the latest version of your script references this a servierlist but doesn’t have any line that references what the file is called or where it is located in the same way the ignore list was. Thanks, Matt

          2. Avatar photo
            Paul Cunningham

            You can use -ServerList and then specify the name of the file containing your list of Exchange servers. You have to provide the name of the file, the script won’t go looking for a specific file name by default.

            The one caveat is that if you use -ServerList the DAG checks are skipped. That isn’t ideal for everyone, I know, but it’s a carry over from legacy code.

    2. Simon Craner

      may bad, yes i did edit wrong line. working now 🙂

      i still get this though just after the “server up” item:
      Cannot convert value “2 968” to type “System.Int32”. Error: “Input string was not in a correct format.”
      At C:TempTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:262 char:18
      + [int]$uptime <<<< = "{0:N0}" -f $uptime
      + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
      + FullyQualifiedErrorId : RuntimeException

      is this what you will be looking at in a fix?

  439. Kerry Denten

    Hi Paul,

    Great script, but I’d really like to see a few extra features added if possible.

    In your original version of this script, you included a check of the DAG and its copies. Any chance that could be added back into this new version?

    Likewise, one of the things we’ve found important to keep an eye on is that all server nodes are seeing all DCs and GCs at all times. We do this by looking at Server Configuration > Server Name > System Settings tab

    If both of these features could be included in your script, it would be hugely helpful.

    Kerry

      1. Kerry Denten

        Thanks so much, Paul.

        Keep up the great work. Your new MVP status is well deserved.

      2. Ed

        thanks mate,

        i was just unblocking when i got your reply 🙂

        thanks a million 🙂

      3. Kerry Denten

        Got a weird one for you Paul.

        I’ve set up a second scheduled task using a slightly modified version of the script .. simply saying “alert” rather than “health check” and with the EXIT added so that if no errors are found, I get no email report.

        Anyway, I keep getting an error on the CA Services on one of my CAS, but if I run “Test-Servicehealth” in Powershell on the server in question, it’s showing that necessary services are running as normal.

        I should also mention that this error does not show in the standard Health Check report, but does show in the ALERT with the EXIT added. The script is scheduled to run on the same server that’s showing the error.

        I’m wondering if you might have any thoughts on what might be happening and how to fix it?

      4. Kerry Denten

        Never mind, Paul. I went back and checked and double-checked my tiny changes, and things are now working as expected with both Scheduled Tasks. The script report is now delivering accurate results.

  440. Ed

    Hi Paul,

    Excellent script, well done.

    i do have a question though, your previous script “How to Set Up an Automated Exchange 2010 Database Backup Alert Email” was followed to the T and it works.

    however, when i try and schedule task this one, i keep getting the ExecutionPolicy error asking me to confirm if i want to run the script. i understand that i have have to Set-ExecutionPolicy Unrestricted, but was wondering if there is an easier way to do this before the script runs ?

    Cheers 🙂

    1. Avatar photo
      Paul Cunningham

      Should be able to just set it once and it will stick… unless you’ve got a GPO or something reverting it?

      1. Ed

        Hi Paul, Thanks for getting back.

        I have set the execution policy to unrestricted and i’m still getting prompted.

        this is the command i’m running
        .Test-ExchangeServerHealth.ps1 -reportmode $true -Sendemail $true

        this is what i get even after 30 seconds of running Set-ExecutionPolicy Unrestricted

        Security Warning
        Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your computer.
        Do you want to run C:scriptsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1?
        [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”):

      2. Avatar photo
        Paul Cunningham

        You may need to right-click the downloaded file and in the properties unblock it.

    2. Paul Bendall

      Setting an execution policy of unrestricted for PowerShell in my view is a very bad idea (although I understand you might do so temporarily). I’d recommend the following process for all scripts dowloaded:
      – Set Execution no lower than remote signed
      – Dowload the script and review the contents, if you aren’t familiar with PowerShell search for set-, new-,add- type cmdlets and if they exist I wouldn’t run the script unless I understood what it is doing as these cmdlets usually change something, get- is fine as it is read-only
      – If possible test in a DEV environment after taking the step
      – Create a new text file then copy and paste the original downloaded file contents to the new text file. Then save the new text file with a ps1 file extension.

      The above process will mean that you are better protected from malware by lowering the execution policy to a dangerous level.

      Paul

  441. Gemmy

    Dear Paul,

    Thanks your script, very nice job!. Currently, I has set the script by using windows task schedule with batch file:

    C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -command “. ‘C:Program FilesMicrosoftExchange ServerbinRemoteExchange.ps1’; Connect-ExchangeServer -auto; F:PSScriptTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

    I can run batch file and receive html email, but when I’ve run task schedule manually, the scheduled task reports with error: The task currently running. (0x41301). I cannot get any results until I stopped. Whats wrong with my configuration?

    Task schedule
    https://www.practical365.com/set-automated-exchange-2010-database-backup-alert-email

    Cheers 🙂

      1. Gemmy

        I use domain admin for testing.

        http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/6e333a49-f04e-4e4e-9ac6-66fd0802859e/

        Anyway, I modified batch file and the problem has been resolved with out “Add-PSSnapin”

        powershell.exe -command “. ‘C:Program FilesMicrosoftExchange ServerbinRemoteExchange.ps1′; Connect-ExchangeServer -auto; F:PSScriptTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

        Thanks Paul for your reply!

        1. Avatar photo
          Paul Cunningham

          Ah okay I see. Yes the script calls the Exchange snapin itself, so your scheduled task should be able to just run the script without having to first load RemoteExchange.ps1

  442. SamuelZ.

    Hi Paul!!

    I’m having this problem.

    Função de Servidor Caixa de Correio Services: Pass
    Add-Member : Não é possível associar o argumento ao parâmetro ‘Name’ porque ele é nulo.
    Em C:ScriptsTest-ExchangeServerHealth.ps1:344 caractere:52
    + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
    -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
    mmand

    1. Avatar photo
      Paul Cunningham

      I would say this is simply a language issue, and the script is checking for a string match in English.

      I’ll try to include a fix in the next update.

      1. EricLemay

        I have the same problem with a french version. Do you have a solution?

        Thank you.

        Add-Member : Impossible de lier l’argument au paramètre « Name », car il a la valeur Null.
        Au niveau de C:adminTest-ExchangeServerHealth.ps1 : 358 Caractère : 52
        + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
        -Force
        + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
        mmand

        1. abdel

          Do you have a solution for this problem?

      2. Rene Joram

        Regarding the errors on Exchange-Server in other languages:

        You have to change the lines 346-349, where there are only the english server-role-names.
        In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
        “Hub-Transport-Serverrolle Services: Pass
        Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

        So you must change (or add lines) e.g. on german exchange-server:

        “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
        “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
        “Mailbox-Serverrolle” { $roleservices = “MB Services” }
        “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

        instead of(or additional to):
        “Client Access Server Role” { $roleservices = “CA Services” }
        “Hub Transport Server Role” { $roleservices = “HT Services” }
        “Mailbox Server Role” { $roleservices = “MB Services” }
        “Unified Messaging Server Role” { $roleservices = “UM Services” }

        Additionally you must change the following line:
        if ($testmailflowresult -eq “Success”)

        to your own language, e.g. on german Exchange Server:
        if ($testmailflowresult -eq “Erfolgreich”).

        You can find the correct word of your language also in the output before you have fixed it:

        Public Folder databases mounted: Pass
        Mailbox databases mounted: Pass
        MAPI connectivity: Pass
        Mail flow test: Erfolgreich

        After these changes the script works fine for my german exchange organisation

        1. lolo

          In spanish too

  443. Mark

    Great script and very useful! Congratulations becoming an MVP, nice job!!

  444. Simon

    Hi Paul,
    thanks for another useful script.

    It runs fine though i do get one scary message right at the beginning of running the script:

    I’ve found that the following line:
    Set-ADServerSettings -ViewEntireForest $true -WarningAction SilentlyContinue

    Generates the error message:
    WARNING: Active Directory server settings remained unchanged.

    After REMing the line out I don’t get the error message and the script continues to run fine. As I’m only interested in one domain I don’t think removing that line is going to make any difference to me.

    Cheers 🙂

    1. Avatar photo
      Paul Cunningham

      Thats just a warning that the setting was already at $true. If your forest only has one domain then you don’t need that line anyway.

  445. Paul Bendall

    In my environment running the script interactively from a CAS and pointing the SMTP server variable at a hub I get the following error:

    Exception calling “Send” with “1” argument(s): “The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.1 Client was not authenticated”

    I’ve come across this before and it can be cured with an additional line that forces authentication. The current line:
    #Send email message
    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)

    becomes

    #Send email message
    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
    $smtp.UseDefaultCredentials = $true

    Hope this might help others

    Paul

    1. Avatar photo
      Paul Cunningham

      Good catch. I’m used to pointing mine at SMTP servers that are already configured for anonymous users, or at a DNS alias for a relay connector that allows anonymous users.

    2. shiraz

      Exception calling “Send” with “1” argument(s): “The SMTP server requires a secure connection or the client was not auth
      enticated. The server response was: 5.7.1 Client was not authenticated”
      At E:Manual ScriptsTest-ExchangeServerHealth.ps1:797 char:13
      + $smtp.Send <<<< ($message)
      + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : DotNetMethodException

      Thanks it works for me

    3. Mohamed Ramadan

      I can’t find this line to add to the script!
      Could any one inform which line is it?
      Thanks

    4. joel

      Thank you so much. It saves me a ton of nose hairs :=)

      It works.

  446. Emmanuel Borbon

    Is it possible to run this script against a list of servers? I don’t want to run it against every exchange server in my organization, just the ones on a specific list.

    1. Avatar photo
      Paul Cunningham

      Yes. There are two ways you could achieve that.

      1) Use the ignorelist.txt file to exclude specific servers.
      2) Modify the $exchangeservers variable so that it only includes the servers you want to check

      eg,

      $exchangeservers = “server1″,”server2″,”server3”

      1. Emmanuel Borbon

        Thanks. It is now running through the list of servers but after it finishes the list it keeps going. Do I need to put something at the end of the list of servers?

      2. Emmanuel Borbon

        Once it finishes running through the servers on the list it starts doing the other servers in my organization.

      3. Avatar photo
        Paul Cunningham

        When you modified $exchangeservers did you replace the existing line of code that sets that variable, or did you add it as an extra line?

        Anyway, I’ll add a parameter to the next version to allow you to specify a filename containing a list of servers to check.

        1. sravani

          Hi Paul,

          Thanks for such a nice script.But have some queries, i wanted to run a script on multiple servers at a time how can i achieve that using the option “-ServerList” .

          How to pass the server names….please help

      4. Emmanuel Borbon

        I replaced the line. Does the list of servers need to be in brackets or anything?

        Being able to to use a file with the server names is great feature. I will watch out for the next version. Thanks.

  447. Ray

    very nice script, thankyou.

    How would I modify it so that it only emails if there is a fail detected ?

    I plan to run the script as a scheduled task every 15 minutes.

    thanx again.

    Ray.

    1. Avatar photo
      Paul Cunningham

      On line 625 there is this:

      $summaryhtml = “< h3 >Exchange Server Health Check Summary
      < p >No Exchange server health alerts or warnings.

      Since that is basically the scenario where no fails were found, adding an EXIT right after that should end the script execution before the email is sent.

      Not the most elegant solution but probably the fastest one I can offer you.

      1. Ray

        Thanx Paul. that worked. cheers.

        1. Andy Helsby

          I’ve also added a line to amend the subject at this point.
          $messageSubject = “Failure: ” + $messageSubject

          This way our noc/alerting software can keep an eye out for the failures and ignore the successful ones. (we actually escalate emails where the subject line contains Failure

      2. Arras

        I’m using the EXIT to stop the script if there is no issues, but it still sends the email. I’m I putting the EXIT in the right spot?

        $summaryhtml = “Exchange Server Health Check Summary
        No Exchange server health alerts or warnings.”
        } EXIT

        1. Avatar photo
          Paul Cunningham

          I will likely include an option in the next version to only email when alerts are detected.

  448. Paul Bendall

    Great script and one I’ll probably use at work. Out of interest do you have a developer background or are you a self taught scripter? I like the aesthetic layout of your scripts as it makes them easy to read, you also tight define variables but you tend not to use functions.

    Although I am quite happy scripting, I taught myself and am concerned I could structure my efforts better than I do.

    Paul

    1. Avatar photo
      Paul Cunningham

      Hi Paul, I’m mostly a self taught scripter, no developer background.

      I write the code in a way that makes it easy for me to read and understand if I have to come back to it later. There is no point wasting effort writing code that you can’t understand when you need that code again, or want to modify it 🙂

  449. Philip

    Running on Exchange 2007 SP1

    1. Avatar photo
      Paul Cunningham

      If you run it from a separate management server or workstation that has PS 2.0 and the Exchange 2007 management tools installed that is another way to resolve the PS 2.0 issue. Or just remove the PS 2.0-syntax comments at the start of the script as suggested earlier.

      There is one Exchange 2007 server in my test lab where I ran the script to make the video above, but I haven’t thoroughly tested it or coded it with Exchange 2007 in mind so I can’t guarantee it will work.

      Let me know how you go.

  450. Philip

    I think I am getting this error because I am running this on PowerShell V1.0. This script is made to run on PowerShell v2.0

    Please can you modify this script to run on Powershell V1.0.

    1. Avatar photo
      Paul Cunningham

      All the comments at the start of the script are in the PS 2.0 syntax. If you remove all those it will probably fix that initial problem, but I don’t plan to make it PS 1.0 compatible otherwise.

      What version of Exchange are you trying to run it for? It is written for Exchange 2010.

  451. Philip

    When I run this script i get this error:

    [PS] C:WindowsSystem32>Test-ExchangeServerHealth.ps1
    Missing closing ‘)’ in expression.
    At C:WindowsSystem32WindowsPowerShellv1.0Test-ExchangeServerHealth.ps1:56
    char:2
    + [ <<<< string]$server,

    Please help me correct this.

    Regards

    Philip

  452. David Woods

    Fantastic! I have been looking around for an “all-in-one” health script.
    BTW: Congrads on your MVP.

  453. Simon Dinney

    Thanks Paul! Another great script as always.. one to add to the daily automated list.

    1. Brenda

      The new script look like it doesn’t inlcude the DAG copy status check (in the original version).

        1. Saroj Kumar Behera

          He Paul,

          I need the latest exchange health check script from you.
          I downloaded one but unable to execute it.

          Do I need to change anything in the script.

          Regards,

          Saroj

        2. Avatar photo
          Paul Cunningham

          What does “unable to execute it” mean? Do you get an error? Have you followed the instructions that are provided with the script?

        3. TLS

          Hi Paul,
          I am Unable Run this scripts as a Scheduler in ExchangeServer2016, But when i run Manually it is working fine.

          [PS] C:\Users\Administrator.Local\Desktop\Test-ExchangeServerHealth>.\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

          Initializing…
          WARNING: The file C:\Users\Administrator.GVA\Desktop\Test-ExchangeServerHealth\ignorelist.txt could not be found. No
          servers, DAGs or databases will be ignored.
          —— Checking EX01
          DNS Check: Pass
          Ping Check: Pass
          Uptime (hrs): 2
          Server version: Exchange 2016
          Roles: Mailbox
          Mailbox Server Role Services: Pass
          Client Access Server Role Services: Pass
          Unified Messaging Server Role Services: Pass
          Hub Transport Server Role Services: Pass
          Total Queue: 0
          Mailbox databases mounted: Pass
          MAPI connectivity: Success
          Mail flow test: Success
          —— Finishing
          Sending email.
          Done.
          [PS] C:\Users\Administrator.Local\Desktop\Test-ExchangeServerHealth>

          Can you please some one create Scheduler as above my path and Export the settings to send me?

          Regards
          TLS

          1. Allen

            Hi Paul,

            I also stuck here. I unable to run health check using Task Scheduler.
            Windows Server OS 2012 R2

            According to your above article steps not working:
            Run whether user is logged on or not
            Run with highest privileges
            Action: Start a program
            Program: powershell.exe
            Arguments: -command “C:\Scripts\ExchangeServerHealth>Test-ExchangeServerHealth.ps1 -Log -SendEmail”

            Cheers,
            Allen

          2. Avatar photo
            Paul Cunningham

            Arguments has an error. Should be a \ instead of the >

          3. Allen

            Hi Paul,

            Here below is my scripts
            -command “& ‘C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1’ -Log -SendEmail”

            I still unable to run from Task Scheduler, here from Log file I can see it just stuck @ loading Exchange Server PowerShell snapin

            Do you know the reasons? But, It can generate if I just copy and run manually from PowerShell Window with exact word.

            06/27/2018 17:02:38 =====================================
            06/27/2018 17:02:38 Exchange Server Health Check
            06/27/2018 17:02:38 06/27/2018 17:02:37
            06/27/2018 17:02:38 =====================================
            06/27/2018 17:02:38 Initializing…
            06/27/2018 17:02:38 Loading the Exchange Server PowerShell snapin

            The task will just show running until I manual cancel the job.

            Please Help.

            Thanks.

            Best Regards,
            Allen

          4. Avatar photo
            Paul Cunningham

            Is the schedule task running with the same credentials you’re using when you manually run the script?

          5. Asif

            Hi,

            I had the same problem. I was able to run the script manually but from schedule task it was failing. I used the below and it worked for me.

            Action: Start a Program
            Program/Script: Powershell.exe
            Add arguments (optional): -File “C:\script\Test-ExchangeServerHealth.ps1” -ReportMode -SendEmail
            Start in (optional): blank

            Thanks,

        4. Tony

          Hi Paul,
          Will I be lucky to add your skype?
          To exchange experiences with each other.
          I am Tony, from Vietnam.

          Thanks,
          IT Manager
          Tony

    2. Paul Ireland

      It would be nice if there were an actual link to download the script.

      1. Will McGlinchey

        If you can’t find it, you don’t belong anywhere near an Exchange server

    3. Rafael Mas

      I have to say Thank you First Paul for this amazing script. I do have a problem I want to clarify with you. On my test which I can’t show the picture of it.. It shows Mail Flow test as failed the same with Database Redundancy and Database Availability.. The rest is all Green Passed.. I don’t have any issues with my DAG or my mail flow.. So not sure why is this happening.

      1. Tim

        I’m having this issue too. Script says failed on all but my 2010 mailbox (not CAS & hub transport) server, but mail is flowing fine.

        1. Avatar photo
          Paul Cunningham

          The mail flow test for 2013 and later relies on a PS remoting connection, which is a bit of a hack to get around problems with Test-MailFlow in those versions. It will fail if there’s a problem with the remoting connection. See my other reply to your other comment.

          1. Dirk

            Hi Paul,

            I have the same problem. Can you please clarify a little bit how this can be fixed?

            Cheers
            Dirk

    4. Hoang

      Hi Paul
      When i run this file, it’s OK. But when i create a task schedule, it doesn’t complete. I check log file, it stop at ” Loading the Exchange Server PowerShell snapin”:

      01/04/2018 11:50:14 =====================================
      01/04/2018 11:50:14 Exchange Server Health Check
      01/04/2018 11:50:14 01/04/2018 11:50:14
      01/04/2018 11:50:14 =====================================
      01/04/2018 11:50:14 Initializing…

      Please you help me to check
      Many thanks!
      01/04/2018 11:50:14 Loading the Exchange Server PowerShell snapin

    5. TLS

      Hi I am Unable this scripts on Scheduler in ExchangeServer2016, But when i run Manually it is working fine.

      [PS] C:\Users\Administrator.Local\Desktop\Test-ExchangeServerHealth>.\Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail

      Initializing…
      WARNING: The file C:\Users\Administrator.GVA\Desktop\Test-ExchangeServerHealth\ignorelist.txt could not be found. No
      servers, DAGs or databases will be ignored.
      —— Checking EX01
      DNS Check: Pass
      Ping Check: Pass
      Uptime (hrs): 2
      Server version: Exchange 2016
      Roles: Mailbox
      Mailbox Server Role Services: Pass
      Client Access Server Role Services: Pass
      Unified Messaging Server Role Services: Pass
      Hub Transport Server Role Services: Pass
      Total Queue: 0
      Mailbox databases mounted: Pass
      MAPI connectivity: Success
      Mail flow test: Success
      —— Finishing
      Sending email.
      Done.
      [PS] C:\Users\Administrator.Local\Desktop\Test-ExchangeServerHealth>

      Can you please some one create Scheduler as above my path and Export the settings to send me?

      Regards
      TLS

Leave a Reply