• Home
  • Topics
    • Office 365
    • Teams
    • SharePoint Online
    • Exchange 2019
    • Exchange 2016
    • Exchange 2013
    • Hybrid
    • Certificates
    • PowerShell
    • Migration
    • Security
    • Azure
  • Blog
  • Podcast
  • Webinars
  • Books
  • About
  • Videos
    • Interview Videos
    • How To Guide Videos
  • Subscribe
    • Facebook
    • Twitter
    • RSS
    • YouTube

Practical 365

You are here: Home / Exchange Server / Test-ExchangeServerHealth.ps1 – PowerShell Script to Generate a Health Check Report for Exchange Server 2016/2013/2010

Test-ExchangeServerHealth.ps1 – PowerShell Script to Generate a Health Check Report for Exchange Server 2016/2013/2010

July 7, 2012 by Paul Cunningham 1,010 Comments

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:

1
.\Test-ExchangeServerHealth.ps1


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

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


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

1
.\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.

1
2
3
4
5
6
7
8
9
10
#...................................
# 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
#...................................
# 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:

1
2
3
4
5
6
7
8
# 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.

Exchange Server Exchange 2010, Exchange 2013, Exchange 2016, PowerShell, Scripts

Comments

  1. Kiran Gandhi says

    January 16, 2022 at 1:46 pm

    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 )

    Reply
    • BobG says

      February 2, 2022 at 5:16 am

      Page through the history here and you’ll find this entry. November 22, 2019. You’re solution is there.

      Franck Ehret says

      November 22, 2019 at 9:52 pm

      In fact, somebody arlready did :

      https://github.com/cunninghamp/Test-ExchangeServerHealth.ps1/pull/36/commits/7a8fc75e0ec3135649b1c7243c19550b7f156a52

      Seems to work fine 😉

      Reply
  2. Dleon says

    August 9, 2021 at 10:34 pm

    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

    Reply
  3. Srdjan says

    July 25, 2021 at 8:16 am

    Hello,

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

    Best regards,
    Srdjan

    Reply
  4. Tom says

    June 23, 2021 at 2:36 pm

    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

    Reply
    • Jose Diaz says

      July 22, 2021 at 3:05 pm

      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

      Reply
  5. Wai Cheng says

    December 20, 2020 at 9:26 am

    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,

    Reply
  6. Prashant N says

    December 1, 2020 at 10:27 pm

    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?

    Reply
  7. TFC says

    September 25, 2020 at 7:32 pm

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

    Reply
  8. Bryan Clark says

    September 10, 2020 at 6:00 am

    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?

    Reply
    • Bryan Clark says

      September 10, 2020 at 7:00 am

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

      Reply
  9. mohd khan says

    July 10, 2020 at 3:45 am

    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.

    Reply
  10. Jean-François Harry says

    April 28, 2020 at 10:43 pm

    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 ?

    Reply
  11. Ken Harrell says

    April 3, 2020 at 4:54 am

    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.

    Reply
  12. Radhey says

    February 21, 2020 at 5:49 pm

    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.

    Reply
  13. alex says

    January 15, 2020 at 11:54 pm

    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

    Reply
  14. Alex says

    January 13, 2020 at 11:40 pm

    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?

    Reply
    • Alex says

      January 14, 2020 at 9:33 pm

      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 !!

      Reply
  15. Rodney Huffaker says

    November 14, 2019 at 5:23 am

    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.

    Reply
    • Franck Ehret says

      November 22, 2019 at 9:34 pm

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

      I’ll really appreciate the updated version !

      Reply
    • Franck Ehret says

      November 22, 2019 at 9:52 pm

      In fact, somebody arlready did :

      https://github.com/cunninghamp/Test-ExchangeServerHealth.ps1/pull/36/commits/7a8fc75e0ec3135649b1c7243c19550b7f156a52

      Seems to work fine 😉

      Reply
      • William says

        November 19, 2021 at 8:09 pm

        Worked for our Exchange 2019 as well.

        Reply
  16. Firman Khairul says

    November 12, 2019 at 6:35 pm

    hi experts

    how send to multiple email address?

    Reply
    • Tim West says

      December 9, 2019 at 12:47 pm

      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.

      Reply
  17. Rajkumar says

    October 25, 2019 at 5:41 am

    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.

    Reply
  18. Muralikrishna Reddy Tekari says

    October 9, 2019 at 7:02 am

    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)

    Reply
  19. fish says

    September 18, 2019 at 8:30 pm

    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!

    Reply
    • Raphl Gu says

      February 23, 2020 at 8:45 pm

      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”

      Reply
  20. Mahmoud Atallah says

    September 16, 2019 at 9:44 pm

    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.

    Reply
  21. Mohan KV says

    September 11, 2019 at 6:03 pm

    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.

    Reply
  22. Mohan KV says

    September 11, 2019 at 6:02 pm

    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.

    Reply
  23. Waylon Irons says

    September 2, 2019 at 11:46 am

    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.

    Reply
  24. Magnolia Carpentier says

    August 10, 2019 at 3:13 pm

    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.

    Reply
  25. Sumit Chaturvedi says

    July 24, 2019 at 1:09 am

    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?

    Reply
  26. haydar tekir says

    July 11, 2019 at 6:44 pm

    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

    Reply
    • Nick says

      April 24, 2020 at 3:48 am

      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?

      Reply
  27. Fred says

    June 18, 2019 at 12:54 am

    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

    Reply
  28. Yasir Khan says

    June 14, 2019 at 2:01 am

    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

    Reply
  29. Shannon says

    May 21, 2019 at 1:57 am

    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.

    Reply
  30. shahin says

    May 15, 2019 at 5:11 pm

    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 ?

    Reply
  31. DAA3805 says

    April 26, 2019 at 2:13 am

    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.

    Reply
  32. Chi says

    February 24, 2019 at 4:23 pm

    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

    Reply
  33. Daniel says

    February 22, 2019 at 3:04 am

    Hi, Paul:

    Very useful script thanks a lot.

    Reply
  34. Arun says

    February 18, 2019 at 4:39 pm

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

    Reply
  35. metin says

    February 10, 2019 at 5:04 am

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

    Reply
  36. Stephan P says

    February 7, 2019 at 5:47 pm

    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

    Reply
  37. Mark F says

    February 5, 2019 at 3:45 am

    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?

    Reply
    • Mark V says

      May 2, 2019 at 7:03 am

      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.

      Reply
      • Mark V says

        May 4, 2019 at 1:44 am

        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.

        Reply
  38. Paul says

    January 17, 2019 at 8:20 am

    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

    Reply
  39. Séb says

    January 16, 2019 at 2:42 am

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

    Thanks,
    Regards

    Reply
  40. Ercan Ufuk GARGIN says

    December 12, 2018 at 10:54 pm

    Hello Paul,

    I found the solution

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

    Regards

    Reply
  41. Ercan Ufuk GARGIN says

    December 12, 2018 at 10:43 pm

    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.

    Reply
  42. Rob says

    October 18, 2018 at 12:13 am

    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!

    Reply
  43. jd says

    October 10, 2018 at 5:57 pm

    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

    Reply
  44. Steve Money says

    September 28, 2018 at 8:34 am

    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?

    Reply
  45. Guillaume Roucou says

    September 11, 2018 at 1:03 am

    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

    Reply
  46. Michael Wawrzyniak says

    August 21, 2018 at 11:32 pm

    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!

    Reply
    • Asela De Costa says

      December 10, 2020 at 12:57 pm

      Thank you so much

      Reply
  47. Bill Bowling says

    August 17, 2018 at 2:37 am

    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

    Reply
  48. Darya says

    June 28, 2018 at 11:06 pm

    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

    Reply
  49. James Ledgard says

    June 22, 2018 at 10:29 pm

    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

    Reply
  50. John says

    May 31, 2018 at 7:31 am

    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)

    Reply
    • John says

      May 31, 2018 at 8:17 am

      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!!!

      Reply
  51. Phil Brooks says

    May 30, 2018 at 12:25 am

    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?

    Reply
    • Paul Cunningham says

      May 30, 2018 at 10:08 am

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

      Reply
  52. John says

    May 26, 2018 at 7:34 am

    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!

    Reply
    • Paul Cunningham says

      May 26, 2018 at 3:54 pm

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

      Reply
  53. SANKARASUBRAMAN PARAMESWARAN says

    May 24, 2018 at 1:11 am

    it is not working for exchange 2016.

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

    Reply
  54. Jon DeSalvatore says

    May 9, 2018 at 4:58 am

    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!

    Reply
    • Paul Cunningham says

      May 9, 2018 at 8:44 am

      Yes, you can configure that threshold in the script.

      Reply
      • Jon DeSalvatore says

        May 9, 2018 at 11:22 am

        Can you guide to where?

        Reply
        • Paul Cunningham says

          May 9, 2018 at 3:44 pm

          Edit the file, scroll down until you find the variables.

          Reply
  55. Jeremy says

    April 14, 2018 at 6:34 am

    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
    #}

    Reply
  56. Andrew says

    April 6, 2018 at 10:13 pm

    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.

    Reply
    • Paul Cunningham says

      April 7, 2018 at 6:24 pm

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

      Reply
      • Paul says

        March 6, 2020 at 3:22 am

        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.

        Reply
  57. Tom says

    March 22, 2018 at 2:52 am

    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

    Reply
    • Paul Cunningham says

      March 22, 2018 at 8:22 am

      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.

      Reply
  58. Fang says

    March 15, 2018 at 6:14 pm

    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!

    Reply
    • Tino says

      May 1, 2018 at 9:13 am

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

      Reply
  59. Gary says

    March 8, 2018 at 11:12 pm

    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

    Reply
  60. Mohsin says

    February 24, 2018 at 4:14 am

    Hi paul,

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

    Regards,
    -Mohsin

    Reply
  61. Mauro says

    February 20, 2018 at 7:55 pm

    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!

    Reply
  62. Christopher says

    February 20, 2018 at 2:08 am

    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

    Reply
  63. Morten Wiingreen says

    February 7, 2018 at 10:06 pm

    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 🙂

    Reply
    • Hilario says

      February 10, 2018 at 3:55 am

      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

      Reply
  64. Kevin C. says

    January 25, 2018 at 6:06 am

    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.

    Reply
    • Paul Cunningham says

      January 25, 2018 at 7:52 am

      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.

      Reply
      • Kevin C. says

        February 2, 2018 at 8:24 am

        Thank you for the suggestion Paul.

        Reply
  65. Chris Smith says

    January 25, 2018 at 2:15 am

    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!!!

    Reply
    • Paul Cunningham says

      January 25, 2018 at 7:50 am

      Any errors when you run the script?

      Reply
      • Chris Smith says

        February 22, 2018 at 1:08 am

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

        Reply
        • Paul Cunningham says

          February 22, 2018 at 6:50 am

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

          Reply
          • Chris Smith says

            March 9, 2018 at 12:52 am

            It is appearing in the report/log file.

            Thanks!!!

  66. Nolan says

    January 1, 2018 at 6:35 am

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

    Reply
  67. Robert says

    December 21, 2017 at 2:12 am

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

    Reply
    • Paul Cunningham says

      December 21, 2017 at 7:05 am

      Just a list of names, one per line.

      SERVER1
      SERVER2
      DATABASE1

      etc

      Reply
  68. Tyson says

    December 14, 2017 at 3:02 am

    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!

    Reply
  69. Troy says

    November 29, 2017 at 5:43 am

    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.

    Reply
    • Paul Cunningham says

      November 29, 2017 at 6:21 am

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

      Reply
      • Troy says

        November 29, 2017 at 6:52 am

        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.

        Reply
  70. John Bales says

    November 29, 2017 at 2:20 am

    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.

    Reply
  71. Dilip Sasikumar says

    November 16, 2017 at 6:02 am

    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?

    Reply
    • Dilip Sasikumar says

      November 16, 2017 at 6:10 am

      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!!

      Reply
      • Morten Wiingreen says

        February 7, 2018 at 9:26 pm

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

        Reply
  72. Andy B says

    November 14, 2017 at 11:57 pm

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

    Many Thanks

    A

    Reply
    • Mark says

      November 15, 2017 at 12:44 am

      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.

      Reply
  73. Chetan says

    October 30, 2017 at 1:56 pm

    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.

    Reply
  74. Joseph Agius says

    October 26, 2017 at 7:58 am

    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

    Reply
    • Paul Cunningham says

      October 26, 2017 at 7:59 am

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

      Reply
      • Joseph Agius says

        October 30, 2017 at 10:49 am

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

        Joseph

        Reply
  75. Amaro Maguni says

    October 24, 2017 at 11:05 pm

    Ok! Great!
    Thanks

    Reply
  76. Amaro Maguni says

    October 24, 2017 at 9:18 pm

    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

    Reply
    • Mark says

      October 24, 2017 at 9:21 pm

      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.

      Reply
      • Amaro Maguni says

        October 24, 2017 at 9:30 pm

        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!

        Reply
        • Mark says

          October 24, 2017 at 9:36 pm

          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.

          Reply
        • Paul Cunningham says

          October 24, 2017 at 9:40 pm

          It would be helpful to show the exact command you’re running.

          Reply
          • Amaro Maguni says

            October 24, 2017 at 9:59 pm

            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,”

          • Paul Cunningham says

            October 24, 2017 at 10:32 pm

            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.

  77. Andi says

    October 19, 2017 at 5:38 am

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

    Reply
  78. misterht says

    October 17, 2017 at 1:50 am

    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.

    Reply
  79. Rajeesh says

    October 10, 2017 at 6:12 pm

    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

    Reply
  80. prasant says

    October 3, 2017 at 2:12 am

    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

    Reply
  81. geots says

    October 2, 2017 at 11:32 pm

    Hi Paul,

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

    Thanks

    Reply
  82. misterht says

    September 27, 2017 at 11:27 pm

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

    Reply
    • Paul Cunningham says

      September 28, 2017 at 11:08 am

      Could you be more specific?

      Reply
      • misterht says

        October 7, 2017 at 5:37 am

        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.

        Reply
        • Paul Cunningham says

          October 7, 2017 at 7:06 am

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

          Reply
          • John says

            May 30, 2018 at 3:46 am

            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!!!!!!!!

          • Paul Cunningham says

            May 30, 2018 at 10:06 am

            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.

  83. Tony says

    September 27, 2017 at 10:47 pm

    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

    Reply
    • Paul Cunningham says

      September 28, 2017 at 11:09 am

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

      Reply
      • Tony says

        September 28, 2017 at 8:47 pm

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

        Reply
  84. Yogesh says

    September 22, 2017 at 7:39 am

    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.

    Reply
  85. Allen says

    September 4, 2017 at 6:47 pm

    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

    Reply
  86. Allen says

    September 1, 2017 at 8:12 pm

    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

    Reply
    • Allen says

      September 1, 2017 at 8:14 pm

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

      Reply
  87. Amit says

    August 22, 2017 at 12:21 pm

    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.

    Reply
    • Paul Cunningham says

      August 22, 2017 at 10:08 pm

      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.

      Reply
      • Mark Bolten says

        September 22, 2017 at 12:24 am

        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.

        Reply
        • Mark Bolten says

          September 22, 2017 at 12:39 am

          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?

          Reply
          • Mark Bolten says

            September 22, 2017 at 12:43 am

            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)’

  88. aKSHAY bAHIRAM says

    August 19, 2017 at 12:52 am

    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

    Reply
    • Paul Cunningham says

      August 19, 2017 at 11:53 am

      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.

      Reply
  89. Amit says

    August 18, 2017 at 6:14 am

    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.

    Reply
    • mario says

      October 7, 2017 at 2:56 am

      have you had any success with this?

      Reply
  90. ajit says

    August 9, 2017 at 3:57 am

    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”

    Reply
  91. David McCarthy says

    August 4, 2017 at 10:18 pm

    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!

    Reply
    • David McCarthy says

      August 25, 2017 at 4:36 am

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

      Reply
      • Paul Cunningham says

        August 25, 2017 at 8:39 am

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

        Reply
  92. David McCarthy says

    August 2, 2017 at 10:37 pm

    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

    Reply
    • Paul Cunningham says

      August 2, 2017 at 10:44 pm

      Have you downloaded the latest version of the script?

      Reply
  93. Matt White says

    July 27, 2017 at 6:34 pm

    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.

    Reply
  94. Jason says

    July 21, 2017 at 8:44 pm

    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

    Reply
    • Paul Cunningham says

      July 24, 2017 at 4:10 pm

      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.

      Reply
      • Jason says

        July 25, 2017 at 7:06 pm

        Hi Paul

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

        Regards

        Jason

        Reply
  95. Preston says

    July 5, 2017 at 11:52 pm

    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.

    Reply
  96. chris says

    June 21, 2017 at 8:06 pm

    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

    Reply
    • Paul Cunningham says

      June 22, 2017 at 11:00 pm

      You can customize those alert thresholds in the script.

      Reply
  97. Kamal says

    June 20, 2017 at 5:06 pm

    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

    Reply
  98. Aftab says

    June 14, 2017 at 10:32 pm

    Hi Paul,

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

    Thanks.

    Reply
    • Paul Cunningham says

      June 14, 2017 at 11:07 pm

      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.

      Reply
  99. Aftab Mohammed says

    June 13, 2017 at 10:44 pm

    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

    Reply
  100. Hans Kristian says

    June 13, 2017 at 8:21 pm

    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.

    Reply
  101. Alex says

    June 7, 2017 at 1:56 am

    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

    Reply
    • Alex says

      June 7, 2017 at 9:30 pm

      Found on your site about Stevie script

      http://www.stevieg.org/2011/06/exchange-environment-report/

      Thx

      Reply
    • Rafal says

      June 8, 2017 at 5:04 pm

      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.

      Reply
  102. Csaba Papp says

    May 22, 2017 at 10:39 pm

    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.

    Reply
  103. sean daly says

    May 12, 2017 at 9:00 pm

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

    Reply
    • Paul Cunningham says

      May 13, 2017 at 9:49 pm

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

      Reply
  104. Eric says

    May 10, 2017 at 6:29 am

    What does the result total queue mean? I have 598

    Reply
    • Paul Cunningham says

      May 10, 2017 at 8:00 am

      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?

      Reply
      • Eric says

        May 10, 2017 at 8:16 am

        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?

        Reply
        • Paul Cunningham says

          May 10, 2017 at 1:33 pm

          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.

          Reply
  105. Patrick Tchuitio says

    May 5, 2017 at 10:49 pm

    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.

    Reply
  106. Sukumar Reddy says

    May 5, 2017 at 12:46 am

    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?

    Reply
    • Paul Cunningham says

      May 5, 2017 at 8:30 am

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

      Reply
  107. TonyD says

    May 3, 2017 at 11:18 pm

    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

    Reply
    • Paul Cunningham says

      May 3, 2017 at 11:34 pm

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

      Reply
  108. Akash says

    May 1, 2017 at 4:07 pm

    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.

    Reply
    • Paul Cunningham says

      May 2, 2017 at 9:54 am

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

      Reply
  109. Kaan says

    April 25, 2017 at 12:07 am

    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.

    Reply
  110. Mohammad Ajan says

    April 9, 2017 at 3:30 pm

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

    Reply
    • Paul Cunningham says

      April 10, 2017 at 9:09 am

      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.

      Reply
  111. Alex Graham says

    April 6, 2017 at 2:52 am

    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?

    Reply
    • Paul Cunningham says

      April 6, 2017 at 8:29 am

      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.

      Reply
      • Mohammad Ajan says

        April 9, 2017 at 3:27 pm

        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

        Reply
  112. Sithandiwe says

    April 3, 2017 at 11:27 pm

    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.

    Reply
    • Paul Cunningham says

      April 4, 2017 at 10:42 am

      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.

      Reply
  113. none says

    March 9, 2017 at 10:38 am

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

    Reply
    • Paul Cunningham says

      March 9, 2017 at 11:20 am

      Thanks. I’ve added it to my issues list in GitHub.

      Reply
  114. ajit says

    March 9, 2017 at 1:55 am

    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

    Reply
    • Paul Cunningham says

      March 9, 2017 at 8:07 am

      Looks like you haven’t set the SMTP settings in the script.

      Reply
  115. ajit says

    March 9, 2017 at 1:38 am

    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

    Reply
  116. Parag says

    February 23, 2017 at 9:16 pm

    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

    Reply
    • Paul Cunningham says

      February 24, 2017 at 9:11 am

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

      Reply
    • Ron says

      April 24, 2017 at 1:31 am

      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.

      Reply
  117. Joseph Liu says

    February 23, 2017 at 1:00 pm

    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

    Reply
    • Paul Cunningham says

      February 24, 2017 at 9:09 am

      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.

      Reply
  118. Jeff Levin says

    February 19, 2017 at 7:19 am

    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?

    Reply
    • Jeff Levin says

      March 1, 2017 at 2:54 am

      Answer at https://social.technet.microsoft.com/Forums/scriptcenter/en-US/d5734b40-8bca-4664-9a43-5163d63d6fde/what-can-cause-a-script-launched-from-explorer-to-fail-when-launched-from-task-scheduler?forum=ITCG#ab976705-c9f9-42df-8a42-b515b2fc711c

      Reply
  119. Prasad Jahagirdar says

    February 17, 2017 at 5:08 pm

    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

    Reply
  120. Padmaraj Vykundam says

    February 13, 2017 at 4:04 pm

    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

    Reply
  121. Ketz says

    February 8, 2017 at 2:17 am

    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.

    Reply
    • Paul Cunningham says

      February 11, 2017 at 4:26 pm

      Anything particular about that server that might be relevant?

      Reply
      • Ketan says

        February 19, 2017 at 6:12 am

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

        Reply
  122. Phil says

    February 7, 2017 at 7:57 am

    $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 🙂

    Reply
    • Phil says

      February 7, 2017 at 7:59 am

      -and not -or.. argh! sorry

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

      Reply
    • Aikiox says

      February 7, 2017 at 4:18 pm

      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

      Reply
  123. Ranjith says

    February 3, 2017 at 9:35 pm

    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?

    Reply
    • Paul Cunningham says

      February 7, 2017 at 8:51 am

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

      Reply
  124. Aikiox says

    February 3, 2017 at 3:11 am

    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

    Reply
  125. Shaik Jahangir says

    February 2, 2017 at 9:37 pm

    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

    Reply
  126. Kumar says

    January 27, 2017 at 11:03 am

    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

    Reply
  127. Jeff Levin says

    January 27, 2017 at 8:27 am

    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.

    Reply
    • Paul Cunningham says

      January 27, 2017 at 9:01 am

      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.

      Reply
      • Jeff Levin says

        February 2, 2017 at 6:28 am

        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?

        Reply
        • Paul Cunningham says

          February 2, 2017 at 2:18 pm

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

          Reply
          • Jeff Levin says

            February 3, 2017 at 1:50 pm

            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.

          • Jeff Levin says

            February 7, 2017 at 7:01 am

            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?

          • Paul Cunningham says

            February 7, 2017 at 8:47 am

            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.

          • Jeff Levin says

            February 8, 2017 at 7:27 am

            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.

          • Paul Cunningham says

            February 8, 2017 at 9:57 am

            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.

          • Jeff Levin says

            February 9, 2017 at 2:42 am

            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.

        • Jeff Levin says

          February 9, 2017 at 3:21 am

          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.

          Reply
        • Paul Cunningham says

          February 9, 2017 at 11:54 am

          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.

          Reply
          • Jeff Levin says

            February 10, 2017 at 7:59 am

            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?

        • Paul Cunningham says

          February 10, 2017 at 8:16 am

          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.

          Reply
          • Jeff Levin says

            February 11, 2017 at 5:23 am

            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?

        • Paul Cunningham says

          February 11, 2017 at 8:21 am

          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.

          Reply
          • Jeff Levin says

            February 14, 2017 at 4:24 am

            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

          • Paul Cunningham says

            February 14, 2017 at 9:17 am

            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.

          • Jeff Levin says

            February 15, 2017 at 1:52 am

            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?

        • Paul Cunningham says

          February 15, 2017 at 8:43 am

          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.

          Reply
          • Jeff Levin says

            February 16, 2017 at 5:48 am

            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.

  128. Michael Hart says

    January 27, 2017 at 1:25 am

    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

    Reply
    • Paul Cunningham says

      January 27, 2017 at 9:00 am

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

      Reply
  129. Anderson Hinojosa says

    January 24, 2017 at 6:56 am

    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

    Reply
  130. Martin Hughes says

    January 18, 2017 at 5:51 am

    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

    Reply
  131. ErikL says

    January 4, 2017 at 4:05 am

    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.

    Reply
  132. ChrisH says

    December 13, 2016 at 2:27 am

    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?

    Reply
    • Paul Cunningham says

      December 13, 2016 at 10:02 am

      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.

      Reply
  133. Jay says

    December 10, 2016 at 1:17 am

    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!

    Reply
    • Jay says

      December 10, 2016 at 2:13 am

      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.

      Reply
  134. stubbo says

    November 15, 2016 at 12:29 am

    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

    Reply
    • Adrian says

      November 19, 2016 at 11:56 pm

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

      Reply
      • peefee says

        December 1, 2016 at 6:19 am

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

        Reply
  135. avi says

    November 11, 2016 at 9:40 am

    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

    Reply
  136. Venkat says

    November 2, 2016 at 6:12 pm

    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”

    Reply
  137. Royal Wang says

    November 2, 2016 at 3:01 pm

    sorry, it is fixed

    Reply
  138. Royal Wang says

    November 2, 2016 at 12:08 pm

    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?

    Reply
  139. Venkat says

    October 25, 2016 at 7:27 pm

    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.

    Reply
  140. Asem Mahmoud says

    October 19, 2016 at 6:50 pm

    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.

    Reply
    • Paul Cunningham says

      October 19, 2016 at 9:05 pm

      Have you modified the script?

      Reply
  141. Christ says

    September 21, 2016 at 12:15 am

    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

    Reply
    • Paul Cunningham says

      September 21, 2016 at 2:06 pm

      Just one item per line, e.g….

      DATABASE01
      DATABASE02
      SERVER01

      Reply
  142. Steve Pasikowski says

    September 15, 2016 at 10:12 pm

    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)

    Reply
    • Paul Cunningham says

      September 21, 2016 at 2:14 pm

      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.

      Reply
  143. Adrian Jackson says

    September 12, 2016 at 6:20 pm

    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.

    Reply
  144. Ihtesham says

    September 8, 2016 at 1:45 am

    Great work…!!! thanks

    Reply
  145. Fergus Strachan says

    September 2, 2016 at 8:41 pm

    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.

    Reply
  146. MikaelJones says

    August 31, 2016 at 11:41 pm

    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?

    Reply
    • Paul Cunningham says

      September 1, 2016 at 8:38 am

      Maybe related to this?

      https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11087637-test-connection-throws-quota-exception-when-passed

      Reply
      • MikaelJones says

        September 2, 2016 at 6:20 pm

        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.

        Reply
        • MikaelJones says

          September 2, 2016 at 6:22 pm

          Doing a manual Test-Connection SERVER01 works fine.

          Reply
        • MikaelJones says

          September 2, 2016 at 6:41 pm

          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 🙂

          Reply
  147. Pierre-Yves PAVAGEAU says

    August 30, 2016 at 11:27 pm

    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
    }
    }

    Reply
  148. Jeff Cothern says

    August 9, 2016 at 2:57 am

    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.

    Reply
    • Pierre-Yves PAVAGEAU says

      August 31, 2016 at 12:23 am

      @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 ?

      Reply
  149. MetaFR says

    July 27, 2016 at 6:10 pm

    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

    Reply
    • Paul Cunningham says

      July 27, 2016 at 7:33 pm

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

      Reply
      • MetaFR says

        July 27, 2016 at 8:36 pm

        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

        Reply
  150. Elmer says

    July 21, 2016 at 3:26 am

    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

    Reply
  151. Mahalakshmi says

    July 15, 2016 at 10:20 pm

    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.

    Reply
  152. rino19ny says

    July 12, 2016 at 4:21 am

    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.

    Reply
  153. Jason says

    July 4, 2016 at 11:32 am

    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

    Reply
    • Jason says

      July 4, 2016 at 1:00 pm

      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
      }
      }

      Reply
      • Adam Borders says

        August 5, 2016 at 9:59 am

        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.

        Reply
  154. Stu Cousins says

    June 29, 2016 at 10:24 pm

    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.

    Reply
    • Paul Cunningham says

      June 30, 2016 at 11:18 am

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

      Reply
      • Stu Cousins says

        June 30, 2016 at 8:45 pm

        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.

        Reply
        • Paul Cunningham says

          June 30, 2016 at 11:03 pm

          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.

          Reply
  155. Phani Chennakesavula says

    June 21, 2016 at 6:28 pm

    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

    Reply
  156. Justin Durlewanger says

    June 15, 2016 at 6:44 am

    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.

    Reply
    • Paul Cunningham says

      June 15, 2016 at 2:03 pm

      Try this fix:

      https://github.com/cunninghamp/Test-ExchangeServerHealth.ps1/issues/5

      Reply
      • Justin Durlewanger says

        June 17, 2016 at 3:10 am

        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!

        Reply
  157. Sumeet Soni says

    June 13, 2016 at 1:56 pm

    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.

    Reply
    • Sumeet Soni says

      June 14, 2016 at 9:39 pm

      Request urgent assistance with this.

      Reply
      • Paul Cunningham says

        June 15, 2016 at 2:01 pm

        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?

        Reply
        • Sumeet Soni says

          June 15, 2016 at 5:08 pm

          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.

          Reply
          • Paul Cunningham says

            June 15, 2016 at 6:24 pm

            Is that with or without your modifications?

  158. David Shriner says

    May 25, 2016 at 3:00 am

    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.

    Reply
  159. Elmer Ernesto Menendez says

    May 18, 2016 at 3:59 am

    Muchas gracias, fue de gran utilidad tu script

    Reply
  160. Gothdoll says

    April 26, 2016 at 7:15 am

    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.

    Reply
    • Paul Cunningham says

      April 26, 2016 at 5:18 pm

      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.

      Reply
  161. james T says

    April 21, 2016 at 11:29 pm

    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

    Reply
  162. Shahir Thottathil says

    April 17, 2016 at 3:13 pm

    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

    Reply
  163. Joe says

    April 14, 2016 at 12:40 am

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

    thanks, great script

    Reply
    • Paul Cunningham says

      April 14, 2016 at 9:16 am

      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.

      Reply
      • Jesse says

        July 21, 2016 at 3:33 am

        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

        Reply
        • Paul Cunningham says

          July 21, 2016 at 10:46 am

          Which fields said “n/a”?

          Reply
  164. naxin says

    April 13, 2016 at 1:25 pm

    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.

    Reply
    • naxin says

      April 13, 2016 at 4:33 pm

      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.

      Reply
    • naxin says

      April 13, 2016 at 5:54 pm

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

      Reply
      • Paul Cunningham says

        April 13, 2016 at 9:28 pm

        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.

        Reply
  165. SteveB says

    April 12, 2016 at 6:28 am

    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.

    Reply
    • Paul Cunningham says

      April 12, 2016 at 9:31 am

      Yes. At the moment I’ve got that in a separate script, because many people like to run it on a separate schedule and have it go to a different set of recipients:

      https://www.practical365.com/set-automated-exchange-2010-database-backup-alert-email/

      I’ve also written it into Exchange Analyzer (https://exchangeanalyzer.com)

      But in the next iteration of the health check script I imagine I will be incorporating that, as it makes sense for them to be together.

      Reply
  166. Lanray says

    April 8, 2016 at 12:42 am

    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!

    Reply
  167. Aerrow says

    April 4, 2016 at 3:27 pm

    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.

    Reply
    • Paul Cunningham says

      April 4, 2016 at 4:05 pm

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

      Reply
  168. Joe Zapata says

    April 1, 2016 at 6:37 am

    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

    Reply
    • Paul Cunningham says

      April 1, 2016 at 8:37 am

      Are you using the recommended scheduled task settings?

      Reply
  169. Mike Nadelman says

    March 21, 2016 at 4:11 am

    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%'”;

    Reply
  170. Mike Nadelman says

    March 21, 2016 at 4:11 am

    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.

    Reply
  171. martin b says

    March 18, 2016 at 2:32 am

    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?

    Reply
  172. Aleem Ijaz Janjua says

    March 11, 2016 at 12:00 am

    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.

    Reply
  173. DeSteeph says

    March 10, 2016 at 10:32 pm

    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?

    Reply
  174. Dwight says

    February 27, 2016 at 10:01 am

    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.

    Reply
  175. prasant says

    February 25, 2016 at 5:29 am

    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

    Reply
  176. prasant says

    February 25, 2016 at 5:11 am

    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

    Reply
  177. prasant says

    February 22, 2016 at 6:09 am

    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

    Reply
  178. Andy says

    February 20, 2016 at 3:36 am

    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

    Reply
    • Andy says

      February 20, 2016 at 3:42 am

      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

      Reply
  179. Navneet says

    February 18, 2016 at 12:20 am

    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

    Reply
    • Paul Cunningham says

      February 18, 2016 at 4:53 pm

      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.

      Reply
  180. Carlos Rotver says

    February 17, 2016 at 6:17 am

    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,

    Reply
    • Paul Cunningham says

      February 18, 2016 at 4:55 pm

      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.

      Reply
      • Carlos Rotver says

        February 19, 2016 at 3:41 am

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

        Reply
  181. prasant says

    February 15, 2016 at 3:36 am

    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

    Reply
  182. Ephibob says

    February 5, 2016 at 1:31 am

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

    Reply
  183. Mohamed Elsayed says

    February 4, 2016 at 2:19 am

    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

    Reply
  184. Gabriel says

    January 26, 2016 at 12:25 am

    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?

    Reply
    • Paul Cunningham says

      January 26, 2016 at 8:28 pm

      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.

      Reply
  185. Paul Sheath says

    January 20, 2016 at 11:17 pm

    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

    Reply
    • Paul Cunningham says

      January 21, 2016 at 11:18 am

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

      Reply
    • 0livier says

      May 7, 2016 at 12:13 am

      Hi Paul,

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

      0livier.

      Reply
      • Paul Cunningham says

        May 7, 2016 at 11:29 am

        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.

        Reply
    • Daniel B says

      April 28, 2017 at 6:47 am

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

      Reply
  186. Stephane Gagne says

    January 19, 2016 at 2:44 am

    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.

    Reply
  187. Sanju says

    December 29, 2015 at 12:31 pm

    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”
    }

    Reply
    • Sanju says

      December 29, 2015 at 4:31 pm

      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

      Reply
      • Sanju says

        January 11, 2016 at 12:20 pm

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

        Reply
  188. Sanju says

    December 18, 2015 at 7:59 pm

    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.

    Reply
    • Paul Cunningham says

      December 20, 2015 at 11:59 am

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

      Reply
      • Sanju says

        December 24, 2015 at 2:00 pm

        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…

        Reply
        • Sanju says

          December 28, 2015 at 11:38 am

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

          Reply
          • Sanju says

            December 29, 2015 at 12:25 pm

            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…

  189. Jack says

    December 9, 2015 at 10:04 am

    Important question mailflow test is external or internal

    Reply
    • Paul Cunningham says

      December 10, 2015 at 4:26 pm

      Internal.

      Reply
  190. sotomayor says

    December 5, 2015 at 1:38 am

    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

    Reply
    • Paul Cunningham says

      December 5, 2015 at 7:52 am

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

      Reply
  191. Claudiu Gheorghe says

    December 4, 2015 at 7:06 am

    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>

    Reply
    • Claudiu Gheorghe says

      December 5, 2015 at 6:46 am

      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.

      Reply
  192. Reynaldo Ruiz Flores says

    November 25, 2015 at 4:17 am

    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

    Reply
    • chris hall says

      November 7, 2018 at 8:13 pm

      I have same issue did you resolve

      Reply
  193. Mukhan says

    November 21, 2015 at 10:44 pm

    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.

    Reply
  194. Glen says

    November 21, 2015 at 7:23 am

    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

    Reply
  195. Mukhan says

    November 19, 2015 at 4:21 am

    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.

    Reply
    • Mukhan says

      November 19, 2015 at 4:26 am

      I have MS Exchange 2010 SP3

      Reply
      • Paul Cunningham says

        November 19, 2015 at 6:09 am

        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.

        Reply
  196. Suraj says

    November 19, 2015 at 12:43 am

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

    Reply
  197. Paul says

    November 18, 2015 at 2:07 am

    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

    Reply
    • Paul Cunningham says

      November 18, 2015 at 8:05 am

      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.

      Reply
  198. Kapil K says

    November 16, 2015 at 4:57 pm

    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

    Reply
    • Paul Cunningham says

      November 16, 2015 at 5:20 pm

      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.

      Reply
  199. Chris says

    November 13, 2015 at 7:27 am

    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?

    Reply
    • Paul Cunningham says

      November 13, 2015 at 9:03 am

      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.

      Reply
      • Chris says

        November 13, 2015 at 10:49 am

        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!

        Reply
  200. Jack Chuong says

    November 5, 2015 at 1:34 pm

    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.

    Reply
    • Jack Chuong says

      November 6, 2015 at 2:14 pm

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

      Reply
  201. Randall says

    October 31, 2015 at 2:48 pm

    Hi Paul

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

    Reply
  202. HerbZ says

    October 29, 2015 at 5:53 am

    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

    Reply
    • randall says

      November 3, 2015 at 1:29 pm

      is actually at the C root

      Reply
  203. Matt says

    October 27, 2015 at 11:23 pm

    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

    Reply
    • John says

      December 17, 2015 at 1:53 am

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

      Reply
      • Paul Cunningham says

        December 17, 2015 at 8:31 am

        Use a distribution group.

        Reply
  204. John says

    October 24, 2015 at 11:21 am

    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.

    Reply
  205. Sanat says

    October 7, 2015 at 3:00 am

    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.

    Reply
  206. Raj says

    October 5, 2015 at 9:52 pm

    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 ?

    Reply
    • Paul Cunningham says

      October 5, 2015 at 10:51 pm

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

      Reply
  207. Manfred Paleit says

    September 25, 2015 at 6:44 pm

    for a simple sort of Servers …

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

    foreach ($server in $exchangeservers) ….

    Reply
  208. Niclas Johansson says

    September 25, 2015 at 5:39 pm

    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.

    Reply
    • Niclas Johansson says

      September 25, 2015 at 6:19 pm

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

      Reply
  209. Manfred Paleit says

    September 25, 2015 at 3:50 pm

    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.

    Reply
  210. Lucas Falconi says

    September 17, 2015 at 3:54 am

    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 ?

    Reply
    • Paul Cunningham says

      September 17, 2015 at 6:37 am

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

      Reply
      • Lucas Falconi says

        September 18, 2015 at 12:09 am

        Hy Paul !

        Always appear in report.

        Reply
  211. Rob Derbyshire says

    September 15, 2015 at 11:48 pm

    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

    Reply
    • Paul Cunningham says

      September 16, 2015 at 2:52 am

      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.

      Reply
      • Brian says

        January 18, 2016 at 4:54 am

        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

        Reply
        • Paul Cunningham says

          January 18, 2016 at 8:50 am

          Same question as above then.

          Reply
          • Matthew McDonald says

            May 5, 2016 at 7:26 am

            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?

        • Aftab says

          June 14, 2017 at 10:24 pm

          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.

          Reply
  212. Krishna says

    August 29, 2015 at 3:09 pm

    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.

    Reply
    • Paul Cunningham says

      August 29, 2015 at 8:14 pm

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

      Reply
      • Krishna says

        September 1, 2015 at 3:52 pm

        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.

        Reply
        • Paul Cunningham says

          September 1, 2015 at 4:50 pm

          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.

          Reply
  213. Paul Slade says

    August 25, 2015 at 1:42 am

    Great script, many thanks.

    Paul.

    Reply
  214. Carlos Rotver says

    August 5, 2015 at 10:50 am

    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??

    Reply
  215. Jijo Antony says

    August 3, 2015 at 4:10 pm

    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.

    Reply
  216. Rana says

    July 23, 2015 at 8:05 pm

    Amazing Wonderful..

    Love the script & the output is amazing :DDDD

    you are the best MAN :DDDD

    Reply
  217. Steven says

    July 20, 2015 at 11:55 am

    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.

    Reply
    • Paul Cunningham says

      July 20, 2015 at 3:56 pm

      Use a distribution list.

      Reply
  218. Kristijan says

    July 14, 2015 at 9:53 pm

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

    Thnx & regards!

    Reply
  219. Kristijan says

    July 14, 2015 at 4:59 pm

    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

    Reply
    • Paul Cunningham says

      July 14, 2015 at 9:13 pm

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

      Reply
  220. Shahid says

    July 10, 2015 at 1:36 am

    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.

    Reply
  221. Shahid says

    July 7, 2015 at 2:25 pm

    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.

    Reply
  222. Shahid says

    July 7, 2015 at 2:23 pm

    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.

    Reply
  223. NashTek says

    July 6, 2015 at 11:03 pm

    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

    Reply
    • NashTek says

      July 7, 2015 at 12:39 am

      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

      Reply
    • Paul Cunningham says

      July 7, 2015 at 10:58 am

      Using a distribution list is the easiest solution.

      Reply
      • NashTek says

        July 7, 2015 at 11:40 pm

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

        Reply
  224. Shahid says

    July 2, 2015 at 1:54 pm

    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

    Reply
    • Paul Cunningham says

      July 3, 2015 at 10:04 pm

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

      Reply
  225. Sachin ladde says

    June 30, 2015 at 11:54 pm

    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.

    Reply
  226. Gabe Foltz says

    June 30, 2015 at 3:07 am

    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.

    Reply
  227. Gabe Foltz says

    June 30, 2015 at 1:59 am

    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?

    Reply
  228. Tausif says

    June 28, 2015 at 8:06 pm

    Thanks Paul!!

    Reply
  229. Tausif says

    June 28, 2015 at 1:48 pm

    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

    Reply
    • Paul Cunningham says

      June 28, 2015 at 2:30 pm

      I have a separate script for that. Here you go:

      https://www.practical365.com/set-automated-exchange-2010-database-backup-alert-email/

      Reply
  230. Frank says

    June 23, 2015 at 11:54 pm

    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

    Reply
  231. Harish Bajaj says

    June 19, 2015 at 3:33 pm

    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.

    Reply
    • Paul Cunningham says

      June 19, 2015 at 3:45 pm

      What is the exact command you are running?

      Reply
      • Harish Bajaj says

        June 19, 2015 at 10:16 pm

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

        than ran the script from Exchange power shell..

        Reply
  232. Chretien says

    June 18, 2015 at 9:16 pm

    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

    Reply
    • Paul Cunningham says

      June 19, 2015 at 11:10 am

      That’s the entire log file?

      Reply
      • Chretien says

        June 19, 2015 at 5:22 pm

        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

        Reply
        • Paul Cunningham says

          June 20, 2015 at 11:14 am

          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?

          Reply
  233. Chretien says

    June 18, 2015 at 8:57 pm

    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

    Reply
  234. Paul says

    June 17, 2015 at 3:56 pm

    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?

    Reply
    • Paul Cunningham says

      June 17, 2015 at 5:42 pm

      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.

      Reply
  235. Chretien says

    June 12, 2015 at 12:25 am

    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

    Reply
    • Paul Cunningham says

      June 12, 2015 at 10:02 am

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

      Reply
  236. Gregory says

    June 11, 2015 at 1:22 am

    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

    Reply
  237. Admin says

    June 10, 2015 at 7:26 am

    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.

    Reply
  238. Essexboy says

    June 5, 2015 at 6:53 am

    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!!

    Reply
    • Paul Cunningham says

      June 6, 2015 at 12:36 pm

      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.

      Reply
  239. Rich says

    May 21, 2015 at 6:42 am

    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.

    Reply
  240. SysAdmin says

    May 7, 2015 at 10:56 am

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

    Reply
  241. SysAdmin says

    May 7, 2015 at 1:55 am

    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

    Reply
    • Paul Cunningham says

      May 7, 2015 at 10:03 am

      Did you edit the script at all?

      Reply
      • SysAdmin says

        May 7, 2015 at 10:18 am

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

        Reply
        • Paul Cunningham says

          May 7, 2015 at 10:30 am

          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.

          Reply
  242. Mohamed Ramadan says

    May 5, 2015 at 3:38 pm

    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?

    Reply
    • Mohamed Ramadan says

      May 5, 2015 at 4:52 pm

      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’

      Reply
      • Paul Cunningham says

        May 6, 2015 at 8:33 pm

        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.

        Reply
  243. Jose Byron Gonzalez says

    May 1, 2015 at 8:33 am

    Or simply create a DL that includes those two people?

    Reply
  244. Alexis Crawford says

    May 1, 2015 at 6:53 am

    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?

    Reply
    • Erik says

      May 1, 2015 at 8:30 am

      did you try “email1;email2” ?

      Reply
    • Paul Cunningham says

      May 1, 2015 at 10:20 am

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

      Reply
  245. Tim Klassen says

    April 29, 2015 at 7:40 am

    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!

    Reply
    • Paul Cunningham says

      April 29, 2015 at 7:44 pm

      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.

      Reply
      • Tim says

        October 17, 2017 at 3:31 am

        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

        Reply
        • Paul Cunningham says

          October 17, 2017 at 7:49 am

          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.

          Reply
          • Tim says

            October 18, 2017 at 11:07 pm

            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)?

          • Paul Cunningham says

            October 19, 2017 at 8:42 am

            It might, yes.

  246. Doug says

    April 21, 2015 at 11:56 pm

    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.

    Reply
  247. CR H. says

    April 14, 2015 at 5:06 am

    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!

    Reply
  248. Anthony says

    April 10, 2015 at 11:03 am

    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?

    Reply
    • Paul Cunningham says

      April 12, 2015 at 7:05 pm

      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.

      Reply
  249. Matt says

    April 1, 2015 at 6:54 am

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

    Reply
  250. shanif says

    March 27, 2015 at 10:41 pm

    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

    Reply
    • June Castillote says

      March 27, 2015 at 10:49 pm

      You may want to check this one out

      http://shaking-off-the-cobwebs.blogspot.com/2015/03/database-backup-and-disk-space-report.html

      Reply
    • Erik says

      March 27, 2015 at 11:07 pm

      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

      Reply
  251. Nick Paolini says

    March 27, 2015 at 4:01 am

    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

    Reply
    • Mike says

      March 27, 2015 at 10:50 pm

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

      Mike

      Reply
  252. Erik says

    March 7, 2015 at 1:53 am

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

    Reply
    • Paul Cunningham says

      March 7, 2015 at 3:44 pm

      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.

      Reply
  253. Phil says

    March 7, 2015 at 1:31 am

    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?

    Reply
  254. IT says

    March 6, 2015 at 11:42 am

    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.

    Reply
    • Paul Cunningham says

      March 6, 2015 at 12:14 pm

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

      Reply
      • IT says

        March 6, 2015 at 1:42 pm

        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.

        Reply
        • IT says

          March 6, 2015 at 1:44 pm

          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)

          Reply
        • Paul Cunningham says

          March 6, 2015 at 1:54 pm

          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.

          Reply
  255. Mike says

    March 5, 2015 at 11:06 pm

    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

    Reply
    • Paul Cunningham says

      March 6, 2015 at 12:13 pm

      Which version of Exchange 2013 are you running?

      Reply
      • Mike says

        March 9, 2015 at 10:33 pm

        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

        Reply
  256. George says

    March 4, 2015 at 8:04 am

    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

    Reply
    • Paul Cunningham says

      March 4, 2015 at 9:50 am

      No downtime required.

      Reply
  257. Frank says

    February 27, 2015 at 10:47 pm

    Great script. Many thanks!!
    I have also written a script in german language to get an overview about Exchange on-premise oraginisations:

    http://www.frankysweb.de/exchange-reporter-2013/

    Reply
  258. Peter says

    February 24, 2015 at 4:18 am

    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!

    Reply
    • Paul Cunningham says

      February 24, 2015 at 9:12 am

      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.

      Reply
  259. Prakash says

    February 16, 2015 at 9:28 pm

    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

    Reply
    • Paul Cunningham says

      February 16, 2015 at 10:55 pm

      Whoops, that got broken with a recent update. I’ll make a note and push out a fix as soon as I can.

      Reply
    • Paul Cunningham says

      March 5, 2015 at 2:44 pm

      This is fixed now in the latest versions available on TechNet or Github.

      Reply
  260. Mohamed Salama says

    February 11, 2015 at 9:28 pm

    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?

    Reply
    • Paul Cunningham says

      February 11, 2015 at 10:39 pm

      Sure thing. Just pushed an update to TechNet and Github to include that change.

      Reply
      • Mohamed Salama says

        February 13, 2015 at 1:41 am

        Thanks for your support 🙂

        Reply
  261. Adam Borders says

    February 11, 2015 at 6:34 am

    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.

    Reply
    • Paul Cunningham says

      February 11, 2015 at 10:40 pm

      Thanks, will test and update the script for that bug.

      Reply
  262. Damian says

    January 24, 2015 at 3:23 am

    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.

    Reply
    • Damian says

      January 24, 2015 at 3:30 am

      Nevermind..I see now you don’t need $true. Saw youtube video of this script being run and that was included.

      Reply
  263. Ian says

    January 23, 2015 at 4:35 am

    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*

    Reply
  264. Nikolas says

    January 13, 2015 at 6:13 am

    As for the command I am using, “-Command .Test-ExchangeServerHealth.ps1 -ReportMode -SendEmail”

    Reply
    • Nikolas says

      January 13, 2015 at 6:22 am

      Paul,

      Awesome that answered my question. Thank you very much!

      Reply
  265. Nikolas says

    January 10, 2015 at 2:39 am

    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?

    Reply
    • Nikolas says

      January 10, 2015 at 4:43 am

      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?

      Reply
      • Paul Cunningham says

        January 11, 2015 at 3:23 pm

        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?

        Reply
        • Nikolas says

          January 13, 2015 at 3:13 am

          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.

          Reply
        • Paul Cunningham says

          January 13, 2015 at 5:44 am

          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

          Reply
  266. Mr. JIT says

    January 8, 2015 at 6:40 am

    Trying to download the script, but taken to my member content page and never gets me to the script download page.

    Reply
    • Paul Cunningham says

      January 8, 2015 at 10:06 am

      I don’t see any registered users in the member site matching the email you’ve used with your comment. Use the contact form here if you need further assistance:

      https://www.practical365.com/contact

      Reply
  267. Mb says

    December 16, 2014 at 4:38 pm

    Hi where do we download this script I cannot find the link anywhere

    thanks

    Reply
  268. Mustafa Zain says

    December 8, 2014 at 8:05 pm

    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,

    Reply
    • BigGreg says

      January 19, 2016 at 9:41 am

      This fixed mt problem with Mail Flow tests failing. Thanks

      Reply
    • BigGreg says

      January 19, 2016 at 9:41 am

      This fixed my problem with Mail Flow tests failing. Thanks

      Reply
  269. Amar Kanta says

    November 19, 2014 at 11:19 pm

    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

    Reply
    • Paul Cunningham says

      November 20, 2014 at 10:41 am

      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.

      Reply
  270. Adam Borders says

    November 18, 2014 at 3:09 am

    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

    Reply
    • Paul Cunningham says

      November 20, 2014 at 10:42 am

      Some bugs with the script like that seem to pop up in co-existence scenarios.

      Reply
  271. Gabe Foltz says

    October 22, 2014 at 9:40 am

    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

    Reply
  272. Andy says

    October 21, 2014 at 1:11 am

    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

    Reply
    • Paul Cunningham says

      October 21, 2014 at 10:12 am

      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.

      Reply
  273. Juanita says

    October 16, 2014 at 10:29 pm

    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

    Reply
    • Paul Cunningham says

      October 17, 2014 at 9:40 am

      Sure. Have you looked at the script mentioned in the article above?

      Reply
  274. Sean says

    October 15, 2014 at 11:52 pm

    Where is the link to download the script(s). If no link how I am able to get it?

    Reply
    • Paul Cunningham says

      October 16, 2014 at 11:35 am

      Yellow box at the end of the article.

      Reply
  275. Chris says

    September 28, 2014 at 7:54 pm

    Hi
    Where can I download this script from… cant find the download button

    Reply
  276. Pär Glanzén says

    September 24, 2014 at 7:46 pm

    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?

    Reply
  277. Ram says

    September 15, 2014 at 6:20 pm

    Steve, the script is not downloadable !

    Reply
    • Ram says

      September 15, 2014 at 6:22 pm

      sorry – it is. rgrds.

      Reply
  278. June Castillote says

    September 14, 2014 at 3:05 pm

    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)
    ———-

    Reply
  279. Vishal Patel says

    August 29, 2014 at 6:00 pm

    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.

    Reply
    • Spyros says

      June 14, 2020 at 1:33 am

      Did you find any solution for the MAPI tests failed?

      Reply
  280. Jeromy Baldridge says

    July 23, 2014 at 6:23 am

    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.

    Reply
    • Paul Cunningham says

      July 23, 2014 at 3:23 pm

      Always great to hear people are successfully customizing the script for their own needs 🙂

      Reply
  281. Gary Libero says

    July 22, 2014 at 1:53 am

    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

    Reply
    • Rosario says

      July 22, 2014 at 6:20 pm

      You may send me that piece of code you changed for review rosario-dot-carco{at}fhnw-dot-ch

      Reply
    • Paul Cunningham says

      July 23, 2014 at 3:35 pm

      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.

      Reply
      • Gary Libero says

        July 24, 2014 at 10:58 pm

        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

        Reply
        • Paul Cunningham says

          July 26, 2014 at 12:16 pm

          You’ll find all the instructions and an FAQ on the page where the script is downloaded.

          Reply
  282. André Winkler says

    July 10, 2014 at 11:52 pm

    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.

    Reply
    • André Winkler says

      July 22, 2014 at 4:46 pm

      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é

      Reply
      • Rosario says

        July 22, 2014 at 6:28 pm

        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

        Reply
  283. Aidan says

    July 3, 2014 at 10:59 pm

    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!

    Reply
    • Paul Cunningham says

      July 3, 2014 at 11:33 pm

      This is covered in the FAQ for the script.

      http://inside.exchangeserverpro.com/members/test-exchangeserverhealth/

      Reply
      • Aidan says

        July 3, 2014 at 11:37 pm

        Sorry! Should have looked, thanks a million Paul!!

        Reply
  284. Jimmy Singal says

    July 1, 2014 at 8:10 pm

    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.

    Reply
    • Aidan says

      July 1, 2014 at 8:31 pm

      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

      Reply
      • Jimmy Singal says

        July 3, 2014 at 1:00 pm

        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.

        Reply
        • Aidan says

          July 3, 2014 at 10:41 pm

          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!

          Reply
        • Paul Cunningham says

          July 3, 2014 at 10:48 pm

          Seriously, just use a distribution list. Then you don’t need to edit the script every time your list of recipients changes.

          Reply
        • Rosario says

          July 3, 2014 at 11:14 pm

          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

          Reply
        • Jimmy Singal says

          July 4, 2014 at 12:19 pm

          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.

          Reply
        • Rosario says

          July 4, 2014 at 6:13 pm

          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

          Reply
  285. Robert says

    July 1, 2014 at 4:36 am

    Disregard ran this Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass and good to go. Thanks!

    Reply
  286. Robert says

    July 1, 2014 at 4:31 am

    Paul,

    When I run the script I get not digitally signed error… ***HELP*** 🙂

    Reply
  287. Jose Byron Gonzalez says

    June 5, 2014 at 3:49 am

    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!

    Reply
    • Paul Cunningham says

      June 5, 2014 at 12:15 pm

      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.

      Reply
  288. Or Elim says

    May 28, 2014 at 4:47 am

    Did anyone managed to migrate this wonderful script to support Exchange 2007?

    Reply
  289. Rob says

    May 13, 2014 at 4:06 am

    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.

    Reply
    • Paul Cunningham says

      May 13, 2014 at 9:55 am

      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?

      Reply
  290. Michael Wiskman says

    April 29, 2014 at 11:11 pm

    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.

    Reply
    • Paul Cunningham says

      April 30, 2014 at 12:46 pm

      You’re welcome. Glad you are finding it useful.

      Reply
  291. luis says

    April 16, 2014 at 7:49 pm

    Thanks Paul. !!!!!!!!!!!!!!!!!!

    Perfect work.

    Reply
  292. martinezjrj says

    February 12, 2014 at 8:41 am

    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

    Reply
  293. martinezjrj says

    February 12, 2014 at 6:51 am

    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

    Reply
    • Paul Cunningham says

      February 12, 2014 at 8:20 am

      Have you modified that line at all?

      Reply
      • martinezjrj says

        February 12, 2014 at 8:33 am

        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

        Reply
        • Paul Cunningham says

          February 12, 2014 at 8:37 am

          The problem will most likely be where you made changes (to the SMTP settings) and haven’t closed a set of quotes properly.

          Reply
  294. Jackson says

    February 5, 2014 at 2:13 am

    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

    Reply
    • Paul Cunningham says

      February 5, 2014 at 9:37 pm

      Good catch, thanks for sharing your experience.

      Reply
  295. Richard says

    January 31, 2014 at 2:03 am

    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?

    Reply
    • Paul Cunningham says

      January 31, 2014 at 12:49 pm

      The script uses the output from Test-ServiceHealth to report the service health status.

      You can run that cmdlet on its own to investigate further:
      https://www.practical365.com/exchange-2013-test-service-health/

      (applies to Exchange 2007/2010/2013)

      Reply
  296. James Ledgard says

    January 29, 2014 at 9:02 pm

    Brilliant script. Thanks for the hard work you and the others put into this.

    Reply
  297. Andre Winkler says

    January 15, 2014 at 6:34 pm

    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.

    Reply
    • Paul Cunningham says

      January 15, 2014 at 11:33 pm

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

      Reply
      • sajeev says

        January 27, 2014 at 3:55 pm

        I tried, but stil unable to read the database mounted information and also the Transport Queue info.

        Reply
    • Andre Winkler says

      January 16, 2014 at 12:30 am

      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é

      Reply
      • Rosario says

        January 16, 2014 at 7:00 pm

        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

        Reply
        • Andre Winkler says

          January 16, 2014 at 7:21 pm

          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é

          Reply
      • Paul Cunningham says

        January 16, 2014 at 11:15 pm

        Download the latest script version (v1.07), it includes a fix for that uptime bug as well as localization strings for non-English systems.

        Reply
  298. Noor says

    January 8, 2014 at 6:33 pm

    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.

    Reply
    • Paul Cunningham says

      January 8, 2014 at 10:38 pm

      What is the exact command you’re running?

      Reply
      • Noor says

        January 9, 2014 at 1:59 am

        Hi Paul,

        I am using ” .Test-ExchangeServerHealth.ps1 -ReportMode $true -SendEmail $true “

        Reply
        • Noor says

          January 9, 2014 at 7:46 pm

          Hi Paul,

          It’s working, Thanks for the Great Script.

          Reply
        • Paul Cunningham says

          January 9, 2014 at 10:18 pm

          No need for the two $true’s there.

          Reply
        • Noor says

          January 12, 2014 at 5:08 am

          Thanks Paul

          Reply
  299. Andrey Ganimedov says

    January 4, 2014 at 1:57 am

    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)})

    Reply
    • Rosario says

      January 4, 2014 at 2:21 am

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

      Reply
  300. Henrik says

    December 12, 2013 at 12:45 am

    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

    Reply
  301. OzDM says

    November 27, 2013 at 1:12 pm

    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.

    Reply
  302. OzDM says

    November 27, 2013 at 10:10 am

    I have signed up, why does it still request i ‘join up’ to download this script?

    Reply
    • Paul Cunningham says

      November 27, 2013 at 10:28 am

      After joining you can login to the members area to access the scripts.

      http://inside.exchangeserverpro.com/members

      Reply
      • OzDM says

        November 27, 2013 at 10:34 am

        I only see 4 scripts. Is that all the content there is?

        Reply
        • Paul Cunningham says

          November 27, 2013 at 10:38 am

          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.

          Reply
        • OzDM says

          November 27, 2013 at 10:41 am

          How do I get access to more scripts? I am interested in the exchange backup reporting and this script.

          Reply
        • Paul Cunningham says

          November 27, 2013 at 11:08 am

          The Get-DailyBackupAlerts.ps1 script is available on the same members page.

          Reply
  303. Phil Smith says

    October 29, 2013 at 5:32 am

    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.

    Reply
    • Paul Cunningham says

      October 29, 2013 at 9:32 am

      Using the -AlertsOnly switch will suppress the email unless there is a warning or error to report.

      Reply
  304. Paul Cunningham says

    October 28, 2013 at 9:13 pm

    V1.06 has just been released

    https://www.practical365.com/test-exchangeserverhealth-ps1-v1-06-now-available/

    Reply
  305. Andrew Golubenkoff says

    October 28, 2013 at 5:38 pm

    Paul,
    Thank you!
    Beta Version – all is OK! Great Work!

    Reply
    • Paul Cunningham says

      October 28, 2013 at 8:35 pm

      Thanks for letting me know 🙂

      Reply
  306. Khalid says

    October 28, 2013 at 4:44 pm

    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

    Reply
    • Paul Cunningham says

      October 28, 2013 at 4:58 pm

      What is the full command that you’re running?

      Reply
      • Khalid says

        October 28, 2013 at 5:05 pm

        .Test-ExchangeServerHealth.ps1 -ReportMode $true

        Reply
        • Paul Cunningham says

          October 28, 2013 at 8:34 pm

          Ok. Please double check the help info included with the script. Correct syntax is:

          .Test-ExchangeServerHealth.ps1 -ReportMode

          Reply
  307. Andrew Golubenkoff says

    October 23, 2013 at 5:26 pm

    TO:
    [int]$uptime = (New-TimeSpan $laststart $now).TotalHours
    [int]$uptime = “{0:N0}” -f $uptime

    Reply
    • Paul Cunningham says

      October 23, 2013 at 9:28 pm

      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

      Reply
      • Rosario says

        October 23, 2013 at 10:24 pm

        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

        Reply
        • Paul Cunningham says

          October 24, 2013 at 8:30 am

          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 🙂

          Reply
  308. Andrew Golubenkoff says

    October 23, 2013 at 5:24 pm

    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!

    Reply
  309. Andrew Golubenkoff says

    October 23, 2013 at 5:15 pm

    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!

    Reply
  310. Atul Mangla says

    October 18, 2013 at 11:41 pm

    Thanks Paul it’s working.

    Reply
  311. Atul Mangla says

    October 18, 2013 at 4:46 pm

    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

    Reply
    • Paul Cunningham says

      October 18, 2013 at 10:48 pm

      Place the server names in the ignorelist on one line each, eg

      server1
      server2
      server3

      Reply
  312. Vidya Sagar says

    October 10, 2013 at 2:03 am

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

    Reply
  313. Sanju says

    September 27, 2013 at 8:37 pm

    Dear Paul,

    Can we please add white space, Free DB disk space and Free Log Disk space free in the next release.

    Regards

    Reply
    • Doug says

      September 27, 2013 at 10:58 pm

      Sanju,

      Steve Goodman has written an Exchange Environment Report script that pulls that information and has been updated to support Exchange 2013. You can download the script here:
      http://www.stevieg.org/2011/06/exchange-environment-report/

      Paul also endorses this script:
      https://www.practical365.com/generate-html-report-exchange-2010-environment/

      Reply
    • Rosario says

      September 28, 2013 at 2:58 am

      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.

      Reply
  314. Sathya Paul says

    September 27, 2013 at 8:02 pm

    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

    Reply
    • Paul Cunningham says

      September 27, 2013 at 8:04 pm

      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.

      Reply
      • Sathya Paul says

        September 27, 2013 at 8:19 pm

        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
        }

        Reply
        • Paul Cunningham says

          September 30, 2013 at 6:23 pm

          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

          Reply
  315. Andrew says

    September 17, 2013 at 12:59 am

    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

    Reply
    • Paul Cunningham says

      September 17, 2013 at 4:32 pm

      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.

      Reply
  316. Ray Cockshell says

    September 4, 2013 at 10:27 am

    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

    Reply
    • Paul Cunningham says

      September 4, 2013 at 8:02 pm

      Interesting. Not a scenario I’d considered. Probably won’t be too hard to account for that in a future version.

      Reply
  317. Erik J says

    September 3, 2013 at 4:47 pm

    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 skipp