Test-ExchangeServerHealth – PowerShell Script to Generate a Health Check Report for Exchange Server 2010

Updated: 5/5/2013 with multiple bug fixes and to include the DAG health check.

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 an email address.

Before you run the script please read the guidance below, and check the known bugs and FAQ at the end of this article for current issues.

Download the script file here: Test-ExchangeServerHealth.ps1 (downloaded 10707 times so far)

The Test-ExchangeServerHealth.ps1 script is run from the Exchange Management Shell. You can use a few builtin parameters to control what it does.

.PARAMETER Server
Perform a health check of a single server

.PARAMETER ReportMode
Set to $true to generate a HTML report. A default file name is used if none is specified.

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

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

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. Please note this has changed since v1.1 so please do not simply paste your customizations from previous versions of the script.

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

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

Download the script file here: Test-ExchangeServerHealth.ps1 (downloaded 10707 times so far)

Please feel free to download and try the script. If you encounter any bugs or have any feedback please leave a comment below. I will do my best to answer each question and deal with any bugs that can be reproduced.

If you’re looking for an example of how to schedule the script to run using Task Scheduler please see this article.

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 -reportmode -sendemail”

Change Log:

  • V1.0, 5/07/2012 – Initial version
  • V1.1, 5/08/2012 – Minor bug fixes and removed Edge Tranport checks
  • V1.0, 5/05/2013 – A lot of bug fixes, updated SMTP to use Send-MailMessage, added DAG health check.

Bugs list and FAQ

Q: Which version of PowerShell is required?

Version 2.0 or higher. If you are running the script on a server that has Exchange 2010 roles or management tools installed then it will have v2.0. If you are running on an Exchange 2007 server check first whether v2.0 is installed. I don’t test the script on v1.0 but you are welcome to modify it as necessary to get it running on a v1.0 environment.

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 is there an error when the script checks the queue for Exchange 2007 Hub Transport servers?

This is a bug that I am working on. The script was not originally intended to be backwards compatible but I will do my best to fix this bug. This should be fixed now in v1.2.

Q: Why do I get errors when the script checks my Edge Transport servers?

Between firewalls and permissions the Edge Transport checks are difficult to account for so in the next version the Edge Transport role will simply be skipped by the script.

Q: Why do I get an error on the server uptime check?

This is a bug that I am working to reproduce and eliminate.

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?

Currently I am working on the following feature improvements:

  • Exchange 2013 compatibility
  • CAS health/connectivity checks
  • Ability to specify a file name containing a static list of servers to check
  • General code cleanup, better verbose output, and a diagnostic log
  • A troubleshooting guide for investigating the issues the script reports in your environment

If you have other health check related features you’d like to see included please let me know in the comments below.

About Paul Cunningham

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

Comments

  1. Simon Dinney says:

    Thanks Paul! Another great script as always.. one to add to the daily automated list.

  2. David Woods says:

    Fantastic! I have been looking around for an “all-in-one” health script.
    BTW: Congrads on your MVP.

  3. When I run this script i get this error:

    [PS] C:\Windows\System32>Test-ExchangeServerHealth.ps1
    Missing closing ‘)’ in expression.
    At C:\Windows\System32\WindowsPowerShell\v1.0\Test-ExchangeServerHealth.ps1:56
    char:2
    + [ <<<< string]$server,

    Please help me correct this.

    Regards

    Philip

  4. I think I am getting this error because I am running this on PowerShell V1.0. This script is made to run on PowerShell v2.0

    Please can you modify this script to run on Powershell V1.0.

    • All the comments at the start of the script are in the PS 2.0 syntax. If you remove all those it will probably fix that initial problem, but I don’t plan to make it PS 1.0 compatible otherwise.

      What version of Exchange are you trying to run it for? It is written for Exchange 2010.

  5. Running on Exchange 2007 SP1

    • If you run it from a separate management server or workstation that has PS 2.0 and the Exchange 2007 management tools installed that is another way to resolve the PS 2.0 issue. Or just remove the PS 2.0-syntax comments at the start of the script as suggested earlier.

      There is one Exchange 2007 server in my test lab where I ran the script to make the video above, but I haven’t thoroughly tested it or coded it with Exchange 2007 in mind so I can’t guarantee it will work.

      Let me know how you go.

  6. Paul Bendall says:

    Great script and one I’ll probably use at work. Out of interest do you have a developer background or are you a self taught scripter? I like the aesthetic layout of your scripts as it makes them easy to read, you also tight define variables but you tend not to use functions.

    Although I am quite happy scripting, I taught myself and am concerned I could structure my efforts better than I do.

    Paul

    • Hi Paul, I’m mostly a self taught scripter, no developer background.

      I write the code in a way that makes it easy for me to read and understand if I have to come back to it later. There is no point wasting effort writing code that you can’t understand when you need that code again, or want to modify it :)

  7. very nice script, thankyou.

    How would I modify it so that it only emails if there is a fail detected ?

    I plan to run the script as a scheduled task every 15 minutes.

    thanx again.

    Ray.

    • On line 625 there is this:

      $summaryhtml = “< h3 >Exchange Server Health Check Summary
      < p >No Exchange server health alerts or warnings.”

      Since that is basically the scenario where no fails were found, adding an EXIT right after that should end the script execution before the email is sent.

      Not the most elegant solution but probably the fastest one I can offer you.

      • Thanx Paul. that worked. cheers.

        • I’ve also added a line to amend the subject at this point.
          $messageSubject = “Failure: ” + $messageSubject

          This way our noc/alerting software can keep an eye out for the failures and ignore the successful ones. (we actually escalate emails where the subject line contains Failure

      • I’m using the EXIT to stop the script if there is no issues, but it still sends the email. I’m I putting the EXIT in the right spot?

        $summaryhtml = “Exchange Server Health Check Summary
        No Exchange server health alerts or warnings.”
        } EXIT

  8. Emmanuel Borbon says:

    Is it possible to run this script against a list of servers? I don’t want to run it against every exchange server in my organization, just the ones on a specific list.

    • Yes. There are two ways you could achieve that.

      1) Use the ignorelist.txt file to exclude specific servers.
      2) Modify the $exchangeservers variable so that it only includes the servers you want to check

      eg,

      $exchangeservers = “server1″,”server2″,”server3″

      • Emmanuel Borbon says:

        Thanks. It is now running through the list of servers but after it finishes the list it keeps going. Do I need to put something at the end of the list of servers?

      • What do you mean “it keeps going”?

      • Emmanuel Borbon says:

        Once it finishes running through the servers on the list it starts doing the other servers in my organization.

      • When you modified $exchangeservers did you replace the existing line of code that sets that variable, or did you add it as an extra line?

        Anyway, I’ll add a parameter to the next version to allow you to specify a filename containing a list of servers to check.

      • Emmanuel Borbon says:

        I replaced the line. Does the list of servers need to be in brackets or anything?

        Being able to to use a file with the server names is great feature. I will watch out for the next version. Thanks.

  9. Paul Bendall says:

    In my environment running the script interactively from a CAS and pointing the SMTP server variable at a hub I get the following error:

    Exception calling “Send” with “1″ argument(s): “The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.1 Client was not authenticated”

    I’ve come across this before and it can be cured with an additional line that forces authentication. The current line:
    #Send email message
    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)

    becomes

    #Send email message
    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)
    $smtp.UseDefaultCredentials = $true

    Hope this might help others

    Paul

    • Good catch. I’m used to pointing mine at SMTP servers that are already configured for anonymous users, or at a DNS alias for a relay connector that allows anonymous users.

    • Exception calling “Send” with “1″ argument(s): “The SMTP server requires a secure connection or the client was not auth
      enticated. The server response was: 5.7.1 Client was not authenticated”
      At E:\Manual Scripts\Test-ExchangeServerHealth.ps1:797 char:13
      + $smtp.Send <<<< ($message)
      + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : DotNetMethodException

      Thanks it works for me

  10. Hi Paul,
    thanks for another useful script.

    It runs fine though i do get one scary message right at the beginning of running the script:

    I’ve found that the following line:
    Set-ADServerSettings -ViewEntireForest $true -WarningAction SilentlyContinue

    Generates the error message:
    WARNING: Active Directory server settings remained unchanged.

    After REMing the line out I don’t get the error message and the script continues to run fine. As I’m only interested in one domain I don’t think removing that line is going to make any difference to me.

    Cheers :)

  11. Great script and very useful! Congratulations becoming an MVP, nice job!!

  12. Hi Paul!!

    I’m having this problem.

    Função de Servidor Caixa de Correio Services: Pass
    Add-Member : Não é possível associar o argumento ao parâmetro ‘Name’ porque ele é nulo.
    Em C:\Scripts\Test-ExchangeServerHealth.ps1:344 caractere:52
    + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
    -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
    mmand

    • I would say this is simply a language issue, and the script is checking for a string match in English.

      I’ll try to include a fix in the next update.

      • Tnkssssssssssssssssssss Paul!!!!!!!

      • I have the same problem with a french version. Do you have a solution?

        Thank you.

        Add-Member : Impossible de lier l’argument au paramètre « Name », car il a la valeur Null.
        Au niveau de C:\admin\Test-ExchangeServerHealth.ps1 : 358 Caractère : 52
        + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
        -Force
        + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
        mmand

      • Regarding the errors on Exchange-Server in other languages:

        You have to change the lines 346-349, where there are only the english server-role-names.
        In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
        “Hub-Transport-Serverrolle Services: Pass
        Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

        So you must change (or add lines) e.g. on german exchange-server:

        “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
        “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
        “Mailbox-Serverrolle” { $roleservices = “MB Services” }
        “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

        instead of(or additional to):
        “Client Access Server Role” { $roleservices = “CA Services” }
        “Hub Transport Server Role” { $roleservices = “HT Services” }
        “Mailbox Server Role” { $roleservices = “MB Services” }
        “Unified Messaging Server Role” { $roleservices = “UM Services” }

        Additionally you must change the following line:
        if ($testmailflowresult -eq “Success”)

        to your own language, e.g. on german Exchange Server:
        if ($testmailflowresult -eq “Erfolgreich”).

        You can find the correct word of your language also in the output before you have fixed it:

        Public Folder databases mounted: Pass
        Mailbox databases mounted: Pass
        MAPI connectivity: Pass
        Mail flow test: Erfolgreich

        After these changes the script works fine for my german exchange organisation

  13. Dear Paul,

    Thanks your script, very nice job!. Currently, I has set the script by using windows task schedule with batch file:

    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command “. ‘C:\Program Files\Microsoft\Exchange Server\bin\RemoteExchange.ps1′; Connect-ExchangeServer -auto; F:\PSScript\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

    I can run batch file and receive html email, but when I’ve run task schedule manually, the scheduled task reports with error: The task currently running. (0×41301). I cannot get any results until I stopped. Whats wrong with my configuration?

    Task schedule
    http://exchangeserverpro.com/set-automated-exchange-2010-database-backup-alert-email

    Cheers :)

  14. Hi Paul,

    Excellent script, well done.

    i do have a question though, your previous script “How to Set Up an Automated Exchange 2010 Database Backup Alert Email” was followed to the T and it works.

    however, when i try and schedule task this one, i keep getting the ExecutionPolicy error asking me to confirm if i want to run the script. i understand that i have have to Set-ExecutionPolicy Unrestricted, but was wondering if there is an easier way to do this before the script runs ?

    Cheers :)

    • Should be able to just set it once and it will stick… unless you’ve got a GPO or something reverting it?

      • Hi Paul, Thanks for getting back.

        I have set the execution policy to unrestricted and i’m still getting prompted.

        this is the command i’m running
        .\Test-ExchangeServerHealth.ps1 -reportmode $true -Sendemail $true

        this is what i get even after 30 seconds of running Set-ExecutionPolicy Unrestricted

        Security Warning
        Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your computer.
        Do you want to run C:\scripts\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1?
        [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”):

      • You may need to right-click the downloaded file and in the properties unblock it.

    • Paul Bendall says:

      Setting an execution policy of unrestricted for PowerShell in my view is a very bad idea (although I understand you might do so temporarily). I’d recommend the following process for all scripts dowloaded:
      - Set Execution no lower than remote signed
      - Dowload the script and review the contents, if you aren’t familiar with PowerShell search for set-, new-,add- type cmdlets and if they exist I wouldn’t run the script unless I understood what it is doing as these cmdlets usually change something, get- is fine as it is read-only
      - If possible test in a DEV environment after taking the step
      - Create a new text file then copy and paste the original downloaded file contents to the new text file. Then save the new text file with a ps1 file extension.

      The above process will mean that you are better protected from malware by lowering the execution policy to a dangerous level.

      Paul

  15. Hi Paul,

    Great script, but I’d really like to see a few extra features added if possible.

    In your original version of this script, you included a check of the DAG and its copies. Any chance that could be added back into this new version?

    Likewise, one of the things we’ve found important to keep an eye on is that all server nodes are seeing all DCs and GCs at all times. We do this by looking at Server Configuration > Server Name > System Settings tab

    If both of these features could be included in your script, it would be hugely helpful.

    Kerry

    • I’ll work on those features, thanks for the feedback.

      • Thanks so much, Paul.

        Keep up the great work. Your new MVP status is well deserved.

      • thanks mate,

        i was just unblocking when i got your reply :)

        thanks a million :)

      • Got a weird one for you Paul.

        I’ve set up a second scheduled task using a slightly modified version of the script .. simply saying “alert” rather than “health check” and with the EXIT added so that if no errors are found, I get no email report.

        Anyway, I keep getting an error on the CA Services on one of my CAS, but if I run “Test-Servicehealth” in Powershell on the server in question, it’s showing that necessary services are running as normal.

        I should also mention that this error does not show in the standard Health Check report, but does show in the ALERT with the EXIT added. The script is scheduled to run on the same server that’s showing the error.

        I’m wondering if you might have any thoughts on what might be happening and how to fix it?

      • Never mind, Paul. I went back and checked and double-checked my tiny changes, and things are now working as expected with both Scheduled Tasks. The script report is now delivering accurate results.

  16. Simon Craner says:

    Great script once again. Because my exchange environment sits in a shared org, i need to target my servers which have a specific naming convention. Which line etc would i put my “where” clause in?

    • Stay tuned, I’m going to update it with some options for being more specific with the servers you test.

      • Simon Craner says:

        I have also tried to change:

        $exchangeservers = “server1″,”server2″ etc

        it still runs through all items in the org and not just check my servers.

        • Perhaps you’ve changed the wrong line. If this was the line you changed…

          $exchangeservers = Get-ExchangeServer $server -ErrorAction Stop

          …that is not the correct one. The script was written with your scenario in mind so suggesting a code change here in the comments is getting a bit tricky in this case.

          I’ll update the script this week with the option to specify a file containing a list of servers to check, but in the meantime I’d suggest just using the ignorelist.txt file to exclude the ones you don’t want to check.

    • Simon Craner says:

      may bad, yes i did edit wrong line. working now :)

      i still get this though just after the “server up” item:
      Cannot convert value “2 968″ to type “System.Int32″. Error: “Input string was not in a correct format.”
      At C:\Temp\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:262 char:18
      + [int]$uptime <<<< = "{0:N0}" -f $uptime
      + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
      + FullyQualifiedErrorId : RuntimeException

      is this what you will be looking at in a fix?

  17. Simon Craner says:

    after a little bit of fiddling i got it to work, but now get an error, not sure if this is due to my changes.

    below is the error from the shell:

    DNS Check: Pass
    Server up: Pass
    Cannot convert value “2 961″ to type “System.Int32″. Error: “Input string was not in a correct format.”
    At C:\Temp\Test-ExchangeServerHealth.ps1:261 char:18
    + [int]$uptime <<<< = "{0:N0}" -f $uptime
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

  18. Hi, Great script, thanks a lot.

    My environment is EX2010&07, anyone has a clue why i get
    “Hub Transport Server Role Services: Fail” on all CAS\HUB servers.

    Regards,
    Rafi.

  19. Hi,

    I see it’s because we don’t use Edge and script check for it’s service:
    Role : Hub Transport Server Role
    RequiredServicesRunning : False
    ServicesRunning : {IISAdmin, MSExchangeADTopology, MSExchangeServiceHost, MSExchangeTransport, MSExchangeTransp
    ortLogSearch, W3Svc, WinRM}
    ServicesNotRunning : {MSExchangeEdgeSync}

    Can we skip it?

    Thx.

  20. Hi,

    Got it as “inheritance” guess i can just set it to be Auto and Running.

    Thanks.

  21. Simon Craner says:

    using the ignorelist i get this error just after it check each one of my servers:

    Cannot convert value “1 422″ to type “System.Int32″. Error: “Input string was not in a correct format.”
    At C:\Temp\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:261 char:18
    + [int]$uptime <<<< = "{0:N0}" -f $uptime
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

    • Seems to be having trouble with the uptime calculation for some reason. I can try and reproduce the bug, but can you give me a clue how long its been since the last time your servers were restarted?

      • Gavin Morrison says:

        Paul, I have seen this as well for the tests against edge servers that are either not on the domain or have restricted access through firewalls from the core network. As a result queries cannot be completed, although in the html report the uptime value seems to be being entered as the same as the previous server in the table due to the conversion error.

  22. Paul,
    when i run the script using SCHEDULE, i get ERRORS on the result email pointing that CA, HT and MB services are not running.

    However this errors are not present when I run the script from PS window, everything shows in GREEN (PASS).

    The schedule is setup using your instruction as given in SET-AUTOMATED-EXCHANGE….. tutorial.
    the action is set to:
    -command “c:\scripts\test-exchangeserverhealth\test-exchangeserverhealth.ps1 -reportmode $true -sendemail $true”

    BRGDS
    Marco

    • Reposting same issue:
      Script running fine from PS command , everything shows in GREEN, but on the email message I get error:
      “Required services not running. Required services not running. Required services not running.”
      reffering to CA Services:Fail; HT Services:Fail; MB Services:Fail.

      What am I doing wrong?

      BRGDS
      Marco

  23. Simon Craner says:

    I have managed to get my health report to work against only my servers and not the entire org.

    instead of using the array command against mailboxserver etc, use the get-exchangeserver command with the pipes to the required where clauses, such as:

    get-exchangeserver | where {$_.name -like “*thisismyserver*”} and so on. “*thisismyserver*” format is the naming convention that you would follow, i.e. you share org with company1 and you are company2, so therefore “*thisismyserver*” would look like this “*company2*”.

    Instead of using the array part again the dag, using where clauses again, targeting only your’s and it works.
    I still get some errors regarding the services not being able to be checked.

    Paul many thanks once again, also edited where the DAG details are and i am targeting only my dag and not all the others.
    Hope this help others.

  24. Hi Paul! great script! works great and quick! I have an issue emailing the report, I get the following error.

    Exception calling “Send” with “1″ argument(s): “Failure sending mail.”
    At E:\reports\scripts\Test-ExchangeServerHealth.ps1:796 char:13
    + $smtp.Send <<<< ($message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    I read the fix above but that didn't work, any ideas?

    • Hi Paul, not sure if you missed this issue….

      • I’ll look into it. Is there any other error details that is provides?

        Have you changed the script variables to point to a valid SMTP server?

        • Yes, it is pointing to the correct smtp server now. Thanks Paul! that corrected it. I had it pointing to the mbx server.

    • Hello Paul.

      I have the same issue as previously mentioned. Single Exchange server 2010 SP1 RU6 running on Windows 2008 R2 SP1 in Hyper-V.

      [PS] D:\scripts>.\TestExchangeServerHealth.ps1 -reportmode:$true -sendemail:$true
      WARNING: Active Directory server settings remained unchanged.
      —— Checking SSTMAIL
      DNS Check: Pass
      Server up: Pass
      Uptime (hrs): 147
      Server version: Exchange 2010
      Roles: Mailbox, ClientAccess, HubTransport
      Mailbox Server Role Services: Pass
      Client Access Server Role Services: Pass
      Hub Transport Server Role Services: Pass
      Total Queue: 0
      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test to SSTMAIL Success
      Exception calling “Send” with “1″ argument(s): “Failure sending mail.”
      At D:\scripts\TestExchangeServerHealth.ps1:795 char:13
      + $smtp.Send <<<< ($message)
      + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : DotNetMethodException

      Thank you for pointing me out, where could be the error. The HTML report is generated. I can find it on the drive in the path where it should be.

      BR
      Jan

  25. Nate-n8 says:

    Thanks for sharing this script.

    I thought the DNS check was clever, but it didn’t report failed when it probably should have. This week we had 2 forward DNS records that got deleted and the System.Net.DNS check still reported it pass. I’m guessing once queried, its cached locally onto that machine? I ran ipconfig /flushdns which it properly failed after that. Any way to always directly query the DNS server or something else rather than having to run flushdns?

    Also, just curious if you have a reason or preference on using System.Net.NetworkInformation.Ping over cmdlet Test-Connection?

    Thanks again!

    • Hi Nate, interesting scenario on that DNS check. I’ll see if there is a practical way to account for it.

      As for the ping method, when this script was originally born it was in PowerShell 1.0. Later when I tried to use Test-Connection I ran into a weird crashing issue further along in the script and traced it back to the use of Test-Connection.

      Some day I hope to get to the bottom of it, or maybe PS 3.0 will solve it for me :)

  26. Mohammed Abid says:

    I am getting error for Edge Server(DMZ) access denied.How to proceed further

  27. Hi Paul,

    Mine works and does its thing but I can’t seem to get the report to be emailed to me.

    I’m running this directly on the exchange server.

    Here is the error I get.

    Exception calling “Send” with “1″ argument(s): “Failure sending mail.”
    At C:\scripts\Test-ExchangeServerHealth.ps1:795 char:13
    + $smtp.Send <<<< ($message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    • That error indicates you haven’t updated the $smtpServer variable in the Email Settings section of the script with a valid entry for your network. Could you double check that please?

  28. Hein Traag says:

    Excellent script Paul. I am getting a nice report in my mailbox. I do have one error in the execution of the script. I get the following error in the shell:

    Cannot convert value “Unable to retrieve uptime” to type “System.Int32″. Error: “Input string was not in a correct form
    at.”
    At C:\********\Tools\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:683 char:19
    + $hours = [int] <<<< $($reportline."uptime (hrs)")
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

    What do i need to change in the script or my environment to make that part work? Running a Exchange 2010 DAG setup here.

  29. Hein Traag says:

    One other thing to ask before turning my attention elsewhere.. we also use a powershell script to check on the health of the databases. I am not much of a coding guru :( and can’t figure out how to include the following into the html report:

    function Get-DatabaseStatistics {
    $Databases = Get-MailboxDatabase -Status
    foreach($Database in $Databases) {
    $DBSize = $Database.DatabaseSize
    $MBCount = @(Get-MailboxStatistics -Database $Database.Name).Count

    $MBAvg = Get-MailboxStatistics -Database $Database.Name |
    %{$_.TotalItemSize.value.ToMb()} |
    Measure-Object -Average

    New-Object PSObject -Property @{
    Server = $Database.Server.Name
    DatabaseName = $Database.Name
    LastFullBackup = $Database.LastFullBackup
    MailboxCount = $MBCount
    “DatabaseSize (GB)” = $DBSize.ToGB()
    “AverageMailboxSize (MB)” = $MBAvg.Average
    “WhiteSpace (MB)” = $Database.AvailableNewMailboxSpace.ToMb()
    }
    }
    }

    Get-DatabaseStatistics | Export-Csv c:\windows\temp\report.csv -Force -NoType

    Send-MailMessage -To *********@yourdomain -From *********@yourdomain -Subject “Mailbox Database Statistics for $((get-date).ToShortDateString())” -SmtpServer yoursmtpserver -Attachments c:\windows\temp\report.csv

    Can’t remember where i got the script so all kudos go to the original author whoever it may be. The report is exported to csv and then mailed but it would be really awesome to have the two scripts combined in a report html that displays the health of the mail servers and the databases they contain.

  30. Shane Bryan says:

    Hi Paul. When I run the script (which is great thank you) I get an error, which I thought was because we have a number of passive servers, but I hope you can clarify.

    We have 5 servers in our Exchange setup accross 2 sites.

    Site 1. 1x Client Access, Hub Transport (both roles on one server) – XCAS01
    Site 1. 2x Mailbox servers – XEXDB01, XEXDB02

    Site 2. 1x Client Access, Hub Transport (both roles on one server) – BCAS01
    Site 2. 1x Mailbox server – BEXDB01

    Site 2 is a DR site.

    When I run this script and generate the email, the 2 CAS servers report a few services, including Mail Flow Test as n/a. The 3 Mailbox servers fail the Mail Flow test. At first I thought this was because we have passive servers, but not all 3 are passive.

    From in the Exchange Management Console, currently XEXDB02 has the mailboxes mounted. The other 2 report that the Copy Status is healthy.

    From this information it may not be possible to provide accurate advice, but any advice is appreciated as to if this is normal behaviour or not.

    Cheers, Shane.

    • Hi Shane, I’ve got that one on my bugs list. Should be pretty simple to stamp out in the next version.

      • Hi Paul,

        That’s great to hear, because like Shane, we’ve been experiencing the exact same problem and have had to abandon using the script for the time being as it’s giving too many incorrect results, particularly as it relates to mailflow on MBX servers.

        Kerry

        • Yep, stay tuned Kerry. Hoping to have an update out soon.

          This is the fun part, when the scripts get run outside of my limited test environments and the bug reports roll in :)

      • Shane Bryan says:

        Ahh thanks Paul (and Kerry, glad to hear it’s not me being a doofus). I planned to schedule this in an email which is delivered to a mailbox that the Helpdesk team check.

        I may put that in place, but let them know not to be alarmed by the red error squares, then update things when the bug is ironed out :-)

        Cheers, Shane.

        • I was thinking about doing a similar thing Shane, but I reckon it could lead to a bit of the “boy who cried wolf” syndrome.

          Y’know, the possibility that once the bug is ironed out, they pay no attention to an alert because they’ve seen so many already, that they ignore what ends up being a genuine problem?

          Kerry

        • Shane Bryan says:

          Yep I’ve put it on hold until the bug is removed :-)

          No point flooding the Helpdesk with information to ignore.

        • The mail flow test fails for me too. I have two sites, with an active mailbox server on one site and a passive mailbox server on the other site.

  31. Paul,
    First of all, thank you for the script. I found an error condition that involves my Edge Transport Server. I run the script from my Exchange server that has the Mailbox, ClientAccess, and HubTransport roles. Next the script queries my EdgeTransport server. Since the EdgeTransport sits in my DMZ and is not actually in my domain, for it I get:
    DNS Check: Pass
    Server Up: Pass
    Access is denied. (Exception from HRESULT: 0×80070005 (E_ACCESSDENIED)
    Uptime (hrs): Unable to retrieve uptime
    Server version: Exchange 2010
    Roles: Edge

    I know why it does that, but like I said, thanks for the script.

    • Next version is going to just exclude Edge Transports for the time being. Between firewalls and permission issues there is a lot to take into account for testing the Edge role.

  32. Paul,,, When it gets to mail flow test I just get the following – *FAILURE*
    Any ideas?

  33. So… I guess an obvious but silly question… I have it set up. And it is working AMAZING. But… if there is a disruption in mailflow for whatever reason… will it still be able to send the email message? LOL. I used the “EXIT” command to stop it if there is not a problem. So… if there is a problem, and it sends the email message, will it still be able to send it? If that makes sense…

    • Valid point. If there is a critical mail flow issue in your environment then of course the report email will also likely not be delivered.

      But the HTML report file that is generated can be used instead in those cases. So if you direct that file to a specific location using the -reportfile parameter, and are running IIS, you can open the HTML report via your web browser (even have it as one of your home tabs for the start of the work day).

  34. I’ve just uploaded v1.1 which has just a few minor bug fixes in it. I’ve also added a bug list/FAQ section to the end of the article to let everyone know which issues I’m working on.

  35. Thanks Paul, great script!!

    Would be great to have this be installed to run at defineable intervals (e.g. every 5 minutes), but only email if the HTML output has materially changed due to a significant change in status (i.e. a server that was down is now up).

    Another idea would be to capture perf statistics (e.g. how many MAPI users are logged on, how many through OWA, etc.). This might be a whole other script or at least not activated by default.

    Tx
    –sc

  36. Hi Paul,

    thanks for that great script. I have an proposal for the health check: We use the Outlook Web Access and Active Sync. Is it possible to include those tests too? That would be great because otherwise i have to check those services with a different script.
    Greets
    Alex

  37. Pradee Purohit says:

    Hi Paul,

    Thanks for your great work. I have 2 queries:

    1. Can we exclude PF databases to be checked? Incase I have PFs remotely over a WAN link?
    2. I am not able to restrict the script to run only on my current Site, it goes to different sites over WAN link and check every server which results in a lot of Red (which I hate to see :) )..

    thank you in advance for your reply.

    Also, could you please suggest nice training material for Powershell for exchange?

  38. Hi Paul,

    On the original script, content indexing is included. Is it possible to include it again? Thanks!

  39. Jason Hauck says:

    Thanks for the awesome script! I’m new to Powershell and 2010 but we just built out our 2010 servers with 4 Mail DB servers in a DAG. Any chance of incorporating something from Get-MailboxDatabaseCopyStatus into the script? I think you said that was coming in a future version, but just checking. It would be a helpful addition for us to know if we need to reseed or anything.

  40. Lee Hutchinson says:

    Great Script! Thanks Paul.

  41. Sahin Boluk says:

    Hi Paul,

    Great Script! Love it! One thing, is it possible to get the number of messages in the Queue in the e-mail report?

  42. Hello Paul,

    I’m not certain how I missed this particular release of yours until today. Good job on the health test script! I’ve recently released something a bit like this but just for using the built in scripts that come with exchange 2010 (http://gallery.technet.microsoft.com/scriptcenter/Troubleshoot-Exchange-2010-aecdc23f). If I rolled in your script as an optional parameter (would set it up to call your script which others would need to manually download from your site to utilize probably) would you mind? Or maybe even the other way around?

    Cheers and thanks again for sharing with the community!

    • Hi Zach, feel free to incorporate any of my scripts into your own however you wish, whether as an external dependency or by reusing code. If its something you’re publicly releasing a credit in your script help/comments would be appreciated :)

  43. Hey Paul,

    Thanks again for being a rock star. I integrated your script into my own as best as I could. If you see any areas of improvement or don’t like my describing your health report as “kick-ass” please let me know and I’ll do my best to fix things up.

    http://gallery.technet.microsoft.com/scriptcenter/Troubleshoot-Exchange-2010-aecdc23f

    The only item I was tempted to change was adding an option to spit out the html report as a returned value and adding a silent mode so I could more easily wrap code around it.. That is not really a feature request though as I’m guessing only a small majority of people using your script are needing that kind of thing (only weirdo fellow scripters like myself).

    Regards,
    Zach

  44. Excellent script, thanks very much.

    One small change I made was to edit line 356 from:
    $false {$svchealth = “Fail”; Write-Host -ForegroundColor $fail “Fail”; $serverObj | Add-Member NoteProperty -Name “Error Details” -Value ($($serverObj.”Error Details”) + $string5) -Force }
    to:
    $false {$svchealth = “Fail”; Write-Host -ForegroundColor $fail “Fail”; $serverObj | Add-Member NoteProperty -Name “Error Details” -Value ($($serverObj.”Error Details”) + $string5 + $s.ServicesNotRunning) -Force }

    Adds the detail from Test-ServiceHealth failure to the Error Details table.

  45. Good morning Paul,

    I was wondering if it would be possible to add to your AWESOME script, a health check of all the “Content Index Catalog”?

    Much appreciated sir :-)

  46. Paul, thank you for script.

    I think it is better to include information about CPU loading and free space at hard drives.

  47. Hemant M. says:

    Hi,
    Paul, its a great script..I have run it in my organization with a success. I want to patch to more options in this script i.e. Disk space alerts and backup alerts.
    how i can go about that.

    Thanks
    Hemant M.

  48. Hi Paul,

    This script is great and i’ve been using it for a while. However I’m getting a false failure on one server for HT services. Tranport and mailflow both are fine. If I check services, all are fine and the server is fully working. Any idea what would cause the false positive?

    thanks
    Paul

  49. Sam O'Donnell says:

    Hi Paul,

    love this script, used at a couple of individual sites and works like a charm! are you planning on implementing DAG and Database Copy status into the script?

    Regards

    Sam

  50. i wanted to use for exchange 2007 in production environment so can you pls help me how can i alter the same and use with exchange 2007.

    What i observed that when i am running the script i am getting the below error but seems to be it is going through. So what change I can do if wann use with exchange 2007 or can I ignore get-ADserver Settings error as I know this is because of exchange 2010, so if I can ignore the error or change something in script to use with exchange 2007. PLs help.. Thanks
    [PS] C:\>.\Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true
    Initializing…
    The term ‘Get-ADServerSettings’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
    path was included, verify that the path is correct and try again.
    At C:\Test-ExchangeServerHealth.ps1:83 char:27
    + if (!(Get-ADServerSettings <<<< ).ViewEntireForest)
    + CategoryInfo : ObjectNotFound: (Get-ADServerSettings:String) []
    , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    —— Checking CASHUB
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 0
    Server version: Exchange 2007
    Roles: ClientAccess, HubTransport
    Client Access Server Role Services: Pass
    Hub Transport Server Role Services: Pass
    Total Queue: 1
    —— Checking MBX
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 0
    Server version: Exchange 2007
    Roles: Mailbox
    Mailbox Server Role Services: Pass
    Mailbox databases mounted: Pass
    Mail flow test: Success

  51. Thank you very much for great script.

    My little troubleshooting about this error, that some got:
    Cannot convert value “1 301″ to type “System.Int32″. Error: “Input string was not in a correct format.”

    You using this statement to format total hours: [int]$uptime = “{0:N0}” -f $uptime

    So because of Russian locale on my servers I have ” ” (space) as Digit grouping symbol.
    That’s why we got “1 301″ in result that cose error to convert into integer value.

    So I just replace one simbol (N to D): [int]$uptime = “{0:D0}” -f $uptime
    And now have no error with this.

    Hope this help.

    PS. In fact I found days in this parameter more helpful, so I change to this:
    [int]$uptime = (New-TimeSpan $laststart $now).TotalDays
    [int]$uptime = “{0:D0}” -f $uptime
    and
    “Uptime (hrs)” to “Uptime (days)”

    Thank you again.

    Waiting for new version of script!

    Best regards,
    Oleg A.

  52. First, I wanted to say what a great report this is, very helpful tool.

    Second, the reason I found this was my search for copy status health checks. Were you able to make any progress on adding that back in?

    Thanks for the great tool
    James Mc

  53. Fredrik Engman says:

    Nice script, looking forward to the DAG checks.

  54. Thanks Paul, excellent script, my only problem is that I have not yet received the HTML report via email :-)

    I have set the smtp info as per above for our environment

  55. Thanks you for the great script! I wanted to add the information that was output after the fail. In my case it looks like this.

    Public Folder databases mounted: Pass
    Mailbox databases mounted: Fail
    Offline databases:
    Mailbox Database DB6

    I’d like to include this in the report.

    Server Errors Warnings
    EXG-SVR2 Mailbox databases not mounted. MAPI tests failed. (currently blank) Mailbox Database DB6

    It would be nice to see what was causing the error in the email.

    How or where can i implement this in the script. I am new to power shell but I do have programming experience.

    Thanks again for this great script!

    Paul

    • A very early version of the script actually did do that but I took it out because (a) the code itself was pretty messy, and (b) it made a terrible mess of the HTML report/email when a server had a bunch of different things wrong with it (eg if the Information Store is down, you get that plus all the DB’s offline plus all the failed MAPI tests so it becomes a big mess in the report).

  56. Great script Paul.
    But i get a strange issue. If I run a script on EMS with reportmode and sendmail parameters (.\Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true) – results as expected.

    Once I schedule a task to run script – all works thou results i get are not correct. I get CA,HT,MB service checks failing all the time on server i run task on.

    Those services are up, I also get Pass results if I run scripts from EMS.

    My Exchange setup is: 2x Exch Servers 2010 SP2 with Mailbox, ClientAccess, HubTransport Roles.
    Looking forward for your comments. Thanks.
    Tom

  57. Scot Whiteley says:

    Hey Paul,

    Great Script. I like it.

    Please can you expand the exchange server version in your next script… For example: Exchange 2010 SP2, server build… blab blab…

    thanks,
    –Scot

  58. Hi Paul,

    The script looks great but I’m not a programmer nor do I have a lot of experience with a command line. Does the script add/modify anything on the server or in AD or make any changes when run? I too am interested in a DAG check as well.

    Thanks,
    Tom

  59. Since everyone keeps asking for a dag database replication report I went ahead and created an initial version based on Paul’s code and another project’s code. Seems to work well enough for me. Let me know what you think. You can grab the script from here:

    http://gallery.technet.microsoft.com/scriptcenter/Exchange-DAG-Replication-d8e99705

  60. Any way you can change your parameters in the next release a little? I rewrote it a bit to be more flexible partially for selfish needs but still could be useful for others.

    Parameters section:

    param (
    [Parameter( Mandatory=$false)]
    [string]$server,

    [Parameter( Mandatory=$false)]
    [bool]$reportmode=$false,

    [Parameter( Mandatory=$false)]
    [string]$reportfile=”exchangeserverhealth.html”,

    [Parameter( Mandatory=$false)]
    [bool]$sendemail=$false,

    [Parameter(Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
    [Alias('SMTP Server')]
    [String]$smtpServer = “localhost”,

    [Parameter(Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
    [Alias('Email Sender')]
    [String]$smtpFrom = “healthcheck@localhost”,

    [Parameter(Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
    [Alias('Email Recipient')]
    [String]$smtpTo = “you@somplace.com”
    )

    • Yeah. Actually all my scripts suffer from some inflexibility when it comes to paramaters and such, relying on editable variables in the script code. I’ve got a priority goal as I update them all for Exchange 2013 to make them more flexible in that sense.

  61. David McKenna says:

    Hi Paul,

    I’m new to this, it works perfectly if I run it in EMS on 2007 but I cannot figure out how to call it from a batch file? Please can you assist?

    Thanks

  62. Thanks for this script.
    I have one issue that I hope you can answer.
    I have pointed the smtp to my smtp server but I still get the:
    Exception calling “Send” with “1″ argument(s): “Failure sending mail.”
    At C:\ntta\Software\Test-ExchangeServerHealth1\Test-ExchangeServerHealth.ps1:809 char:13
    + $smtp.Send <<<< ($message)
    Error.
    My SMTP server is configured to accept on port 587.
    Is the script attempting to send on port 25? How do we change this?

  63. This script has been a great help but we have noticed an oddity. We run the script in a scheduled task. The task calls a batch file with in turns calls the power shell script. Here is the oddity. when called by the scheduled task one of our exchange servers reports three failures, CA HT, and MB services. When I run the batch file myself, double clicking the batch file, the report shows no failures. The batch file is called using the same credentials. The only difference is a scheduled task is calling the batch file and not by a user clicking the the batch file.

    get-reports.bat

    Scheduled task reports failures.
    User double click reports no failures.

    any thought on this?

    Thanks,

    Paul

  64. The script file has been saved to the C:\temp folder on our Exchange server.

    The following command is run in EMS version 2.0 on the Exchange server.

    [PS] C:\temp>Test-ExchangeServerHealth.PS1 -server EXG

    Result as follows:

    [PS] C:\temp>Test-ExchangeServerHealth.PS1 -server EXG
    The term ‘Test-ExchangeServerHealth.PS1′ is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:30
    + Test-ExchangeServerHealth.PS1 <<<

    Can anyone tell me why this is not working?

    • Helps if I actually extract the script files. Now I get this.

      [PS] C:\temp>.\Test-ExchangeServerHealth.PS1 -server HADEG
      File C:\temp\Test-ExchangeServerHealth.ps1 cannot be loaded. The file C:\temp\Test-ExchangeServerHealth.ps1 is not digi
      tally signed. The script will not execute on the system. Please see “get-help about_signing” for more details..
      At line:1 char:32
      + .\Test-ExchangeServerHealth.PS1 <<<

      • I see. OK that’s it for today. I’ll try this next week.

        TO PERMIT SIGNED SCRIPTS TO RUN
        ——————————-
        When you start Windows PowerShell on a computer for the first time, the
        Restricted execution policy (the default) is likely to be in effect.

        The Restricted policy does not permit any scripts to run.

        To find the effective execution policy on your computer, type:

        get-executionpolicy

        To run unsigned scripts that you write on your local computer and signed
        scripts from other users, use the following command to change the execution
        policy on the computer to RemoteSigned:

        set-executionpolicy remotesigned

        For more information, see Set-ExecutionPolicy.

        RUNNING UNSIGNED SCRIPTS (REMOTESIGNED EXECUTION POLICY)
        – More –

      • I am getting the same error. Any idea what resolved this for you?

  65. Sahin Boluk says:

    Hi,

    Is it possible to only get an e-mail if there is a failure? What I want to do is setup a task to run every 10 minutes or so, and only send an e-mail if something fails.

  66. TRAN XUAN QUANG says:

    when I run the script “Test-ExchangeServerHealth.ps1″ it appear the message
    “Call was canceled by the message filter. (Exception from HRESULT: 0×80010002 (RPC_E_CALL_CANCELED))”

    I want to check time to replicate from DC site to DR site (Server name: DR-mailbox-03 to HQ-mailbox-03), I also to know time to connected two server.

  67. I have Exchange 2013 installed on my lab and i try your script its showing me this error

    [PS] E:\script>.\Test-ExchangeServerHealth.ps1 -server ex
    Initializing…
    —— Checking EX
    DNS Check: Pass
    Server up: Exception calling “Send” with “1″ argument(s): “An exception occurred during a Ping request.”
    At E:\script\Test-ExchangeServerHealth.ps1:248 char:4
    + $result = $ping.send($ip)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : PingException

    You cannot call a method on a null-valued expression.
    At E:\script\Test-ExchangeServerHealth.ps1:249 char:8
    + if ($result.status.ToString() -eq “Success”)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  68. I ended up tweaking the email section in the script so it would just go out my Outlook application.

    if ($sendemail)
    {

    $ol = New-Object -comObject Outlook.Application
    $mail = $ol.CreateItem(0)
    $Mail.Recipients.Add($smtpto)
    $Mail.Subject = $messageSubject
    $Mail.HTMLBody = $htmlreport

    $Mail.Send()
    }

    Very much waiting for the DAG health section.

    One additional question that I think has been asked already in the comment but I will ask again. We have two MX servers and one of them does not have any datastores active on it and I get the following warning on the passive DAG server.

    Mail flow test: WARNING: Exchange can’t perform the mail flow test because currently there are no mailbox databases on server *SEVERNAMETAKENOUT*.

  69. Hi Paul,

    Great script!! Need some help in adding this script to Task Scheduler for a daily email report. I have added the option -reportmode $true -sendemail $true in the “Add Argument” section in Task Scheduler and powershell.exe “program/script” but it doesn’t work!!

    Kindly assist me!!

    Regards
    Akash

  70. Thank you so much for sharing this magnificent piece of work.
    You have obviously put a lot of effort into this, not just the script but also the commentary and how-to guides

    Thank you again

    P.S> I’m a big fan of your articles and have used many of them in the past. Keep up the good work !!!

  71. Helllo, thank you, but need some help.

    I getting this error

    Mailbox databases mounted: Pass
    Mail flow test: No active mailbox databases
    —— Checking RU-EXCH1
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 352
    Server version: Exchange 2010
    Roles: Mailbox
    Роль сервера почтовых ящиков Services: Pass
    Add-Member : argument parametr”Name”, value NULL.
    C:\scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1:358 знак:52
    + $serverObj | Add-Member NoteProperty -Name <<<< $roleservices -Value $svchealth
    -Force
    + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
    mmand

    Mailbox databases mounted: Pass
    MAPI connectivity: Pass

    • This is probably a problem due to non-English language and it is something I am trying to fix in the next version.

    • i am using russian version of Exchange 2010 and R2, maybe i need to resave ps1 in utf8 format or set encoding string somewhre?

    • Regarding the errors on Exchange-Server in other languages:

      You have to change the lines 346-349, where there are only the english server-role-names.
      In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
      “Hub-Transport-Serverrolle Services: Pass
      Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

      So you must change (or add lines) e.g. on german exchange-server:

      “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
      “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
      “Mailbox-Serverrolle” { $roleservices = “MB Services” }
      “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

      instead of(or additional to):
      “Client Access Server Role” { $roleservices = “CA Services” }
      “Hub Transport Server Role” { $roleservices = “HT Services” }
      “Mailbox Server Role” { $roleservices = “MB Services” }
      “Unified Messaging Server Role” { $roleservices = “UM Services” }

      Additionally you must change the following line:
      if ($testmailflowresult -eq “Success”)

      to your own language, e.g. on german Exchange Server:
      if ($testmailflowresult -eq “Erfolgreich”).

      You can find the correct word of your language also in the output before you have fixed it:

      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test: Erfolgreich

      After these changes the script works fine for my german exchange organisation

  72. Hi Paul,

    Is it possible to run this script with SCOM 2012 server.?

  73. Paul

    Is there an updated version of the script yet? I have a July 2012 version still.

    Kind Regards

    Cathryn

    • The latest version (same download link above) is from August 2012 and fixes a few bugs in that earlier version.

      A new version will be coming in the next few weeks I hope.

  74. Bill Michaels says:

    Hey Paul,

    I am using PS 3.0 and the send mail feature has changed it should be send-mailmessage.

    I can’t figure out what all to change in your script for me to get an email sent

    any help would greatly be appreciated

    Thanks Bill

  75. Keith K. says:

    Another Great script!

    I have about 50 servers in my environment. Is there a way to have the script run the report by alphabetical server name? I have the servers hard-coded into the script alphabetically but it doesn’t seem to work.

  76. Paul,
    I have used the scripted and you did a very good job.
    However I do not want to run this script from any of the Exchange servers, because if this particular server fails, I will not get any report. So I thought it would be good idea to install it on separate server.

    What do I need to install on a separate Win 2008 R2 server to run the script with success? Do I need to install the Exchange System Management Tools or is it enough to have a PowerShell with some additional add-ins?
    Mike

    • You can certainly install the management console but you can do it remotely as well. Check out the manual section in this link to set up a “new-pssession“.

      http://www.mikepfeiffer.net/2010/02/managing-exchange-2010-with-remote-powershell/

      • Thx Stephen – nice article.
        I have tried that.
        I have open the Power Shell on the Win 2008 R2 computer, and run the following command to connect to the Exchange remotely:

        $s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange FQDN]/PowerShell/ -Authentication Kerberos

        Import-PSSession $s

        And I cannot get through one thing – I cannot get this command to work on the remote server which doesn’t have Exchange manangement tools installed.

        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

        This command is one of the first in the scipt written by Paul.
        Do you have any idea how to overcome it?

  77. When I run script via Exchange powershell all roles services indicate as PASS with green color
    but
    When I run script via Task Scheduler all roles services indicate as Fail with red color.

    please help me on this.

  78. Paul,

    Love the script, have used it for 6 months or so and it really helps me have a quick look to identify any issues that I would normally have to log into each server and run checks manually.

    My only issue is that recently we have moved a couple of servers out of a DAG, but they are still in service because they have public folders that are in use, until we can move and decom. During the test, those servers warn (which I expect) during the mail flow test that “No mailbox databases”.

    However, once the checks continue on to other servers that DO have mailbox databases available, I continue to get the warning message. I’m not a programmer by any stretch, but is it possible that the result for that test doesn’t get re-initialized?

    Thanks for all you do in helping us admins survive!

  79. Paul,

    How can i get the script to report the queue length as a number, instead of Pass/Fail in the email report?

    • My current version lists the queue count next to the pass/fail result. Not sure if that is in the publicly released on yet though, but it will be in the next version I release.

  80. SREEJITH says:

    Hi Paul,

    Thanks for your script.

    I have a small issue. Please help me.

    I am supporting different clients with 2010 and 2007 exchange. I have implemented this script via task for exchange 2010 and working fine.

    But recently i did this for one of my 2007Box and i am getting the full result only if i manually run the script in exchange / windows powershell.

    if i run it via task i amnot getting the full details. after the summary the exchange health check details not showing. Please see the below sample report

    Exchange Server Health Check Report
    Generated: 04/02/2013 21:28:05
    Exchange Server Health Check Summary
    No Exchange server health alerts or warnings.

    Note: If i run the script directly from shell, i am getting all the results.

    Please help me..

    Thank You
    Sreejith

    • The script is written to work with Exchange 2010. I suspect what you will need to do is replace the section early in the script that calls the Exchange 2010 snapin with the name of the Exchange 2007 snapin instead.

  81. Paul,

    Great stuff this script , we use it 24/7.
    Any word on when the new 1.2 version will be ready for download?
    Can’t wait!

  82. To all who want to use this script with different language-Exchange-Servers:

    Regarding the errors on Exchange-Server in other languages:

    You have to change the lines 346-349, where there are only the english server-role-names.
    In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
    “Hub-Transport-Serverrolle Services: Pass
    Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

    So you must change (or add lines) e.g. on german exchange-server:

    “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
    “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
    “Mailbox-Serverrolle” { $roleservices = “MB Services” }
    “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

    instead of(or additional to):
    “Client Access Server Role” { $roleservices = “CA Services” }
    “Hub Transport Server Role” { $roleservices = “HT Services” }
    “Mailbox Server Role” { $roleservices = “MB Services” }
    “Unified Messaging Server Role” { $roleservices = “UM Services” }

    Additionally you must change the following line:
    if ($testmailflowresult -eq “Success”)

    to your own language, e.g. on german Exchange Server:
    if ($testmailflowresult -eq “Erfolgreich”).

    You can find the correct word of your language also in the output before you have fixed it:

    Public Folder databases mounted: Pass
    Mailbox databases mounted: Pass
    MAPI connectivity: Pass
    Mail flow test: Erfolgreich

    After these changes the script works fine for my german exchange organisation

  83. Paul,

    i’m still struggling to bring “test-owaconnectivity” and “test-activesyncconnectivity” to your script. Everything else is working flawless, but i got everytime a bunch of error messages by implement other cmdlets besides the existing ones.

    You have a hint to do that?

    Thanks, Flo

  84. The script has been updated to v1.2, available at the same download link. This version includes several bug fixes and also adds the DAG health check.

    Please review the notes and instructions as some things have changed, eg the SMTP settings that you customize.

    Thanks everyone for your feedback and bug reports so far.

  85. Shane Bryan says:

    Works perfectly, thanks Paul. awesome stuff that’s truly appreciated :-)

    Cheers Shane.

  86. G’day Paul,

    Stellar work on this version of the health script. Works a treat with just a couple of tweaks to the batch file we use to run it.

    Would it be possible to stretch the friendship and ask if it’s possible to include storage usage, eg, available/used/overall per HDD or per LUN/array?

    Kerry

    • I have been experimenting with that and the biggest challenge is accounting for all the different mixes of dedicated log/DB LUNs vs shared log and shared DB LUNs vs multiple databases on a single LUN and so on and so on, while still presenting the results in a useful way.

      Of course I love a challenge, so I will probably get it done some day, just not any time soon to be honest :)

  87. Thanks Paul. Grate script as usual.

    I remember in your previous script you had a column for backup as well, I don’t see in this script.

    Question: I am new to this Exchange 2010 and still struggling with many things.
    After I run this script I found error in Cluster Network (Failed). When I checked in DAGNetwork01 configuration it shows [subnets] 10.32.100.0/24 is Misconfigured, whereas DAGNetwork02 [Subnets] shows fe80::/64 Unknown.
    Any suggests how to fix it.
    Thanks

  88. kwannapa says:

    Hi Paul,

    I trying to run the script for send report to me. But it’s couldn’t send mail to me. I ran the scripts on the Hub Server and i change the smtp settings already. This is the results after ran the scripts is show below.

    —- Server Test-Replication Report —-

    Server ClusterServ ReplayServi ActiveManag TasksRpcLis TcpListener DagMembersU ClusterNetw QuorumGroup FileShareQu
    ice ce er tener p ork orum
    —— ———– ———– ———– ———– ———– ———– ———– ———– ———–
    MBXPN01 Passed Passed Passed Passed Passed Passed Passed Passed Passed
    MBXPR01
    MBXPR02 Passed Passed Passed Passed Passed Passed Passed Passed Passed

    —— Finishing
    Done.
    [PS] D:\Script\Test-ExchangeServerHealth>

    Thanks

    • kwannapa says:

      and have this error :

      Windows Failover Clustering encountered a transient error. Trying the operation again may be successful. Error: ‘IsNod
      Clustered’.
      + CategoryInfo : NotSpecified: (0:Int32) [Test-ReplicationHealth], ExClusTransientException
      + FullyQualifiedErrorId : 33AD0105,Microsoft.Exchange.Monitoring.TestReplicationHealth

      Add-Member : Cannot bind argument to parameter ‘Name’ because it is null.
      At D:\Script\Test-ExchangeServerHealth\Test-ExchangeServerHealth.ps1:880 char:47
      + $memberObj | Add-Member NoteProperty -Name <<<< $($healthitem.Check) -Value $($healthitem.Result)
      + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
      + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
      mmand

      Thanks a lot

    • What is the full command you’re using to run the script?

      • kwannapa says:

        [PS] D:\Script\Test-ExchangeServerHealth>.\Test-ExchangeServerHealth.ps1

        This is command i ran it.

        Thank for your quickly answer

        • Can you please review the instructions in the article again. They explain how to run the script to get an email report sent to you.

        • kwannapa says:

          i set the schedule task that you recommend Arguments: -command “C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -reportmode -sendemail” and then i click run this schedule task but i don’t received the mail report to me. Not sure why its don’t send mail to me. and i confirm that i change the smtp settings already.

        • Try running it in your Exchange Management Shell:

          .\Test-ExchangeServerHealth.ps1 -reportmode -sendemail

          That way you’ll see any errors that occur when the email is attempting to send.

          It is also worth double checking the email settings you’ve configured. Often people make a typo or miss a closing quote and it fails as a result. You should also make sure the server you’re running the script from is in the list of allowed IP addresses for the relay connector you’re pointing it at.

        • kwannapa says:

          Thanks you very much Paul :D

  89. Sahin Boluk says:

    Hi Paul,

    Love your script. I used the previous version like a charm! Had it set on a schedule task and only e-mail if there was a failure.

    In the new version, not sure where to put the ‘Exit’ command so it doesn’t send an e-mail if there are no Server or DAG Health issues.

    Second, if there is a DAG issue, it doesn’t say that in the email. Says the following:

    Exchange Server Health Check Summary
    No Exchange server health alerts or warnings
    Exchange Server 2010/2007 Health

    Maybe add something after the “No Exchange Server Health Alerts or Warning” if there are any DAG issues so we can scroll down to take a look.

    Thanks again!

    • Correct, that summary only refers to server health at the moment, not DAG health. I will be adding more summary details in the next version.

      But generally speaking I recommend people at least skim through the entire report looking for yellow/green rather than just rely on the summary :)

  90. Thanks Paul for your update

  91. Paul,

    Thanks for the updated server health check script! We greatly appreciate the freebies you provide to help us monitor Exchange. :-)

    I’ve tried to modify the script so that emails are only sent when there is an error or warning detected. In the process I noticed two variables called $alerts and $AlertsOnly. I tried to use the AlertsOnly as a switch as listed in line 139 but was unable to get it to work. I read through the comments section as well and noticed you mentioned adding the feature of only emailing if an issue was found. Suggestions?

    Thanks!! :-)

    • Looks like some code slipped in for the “Alerts Only” option that I haven’t finished fully implementing and testing yet. I have it on my list of improvements I’m working on.

  92. is there any script for performance metrics for exchange server

    -jeevan

  93. Philipp Rusch says:

    Hi Paul,
    I am using your script on a fresh Exchange 2010 Server and cannot get the serverroles-checks to work.
    I always get something like “invalid argument, because it is NULL”, when binding parameter $serverinfoservices to -Name. Sorry that I can’t be more specific since I have the german version and have to translate this back to english

    • The script still has some issues with non-English languages that I haven’t gotten around to fixing.

      Go to line 495 in the script and adjust the server role names there to your language and see if that fixes it.

    • Hi Philipp,
      I already mentioned the changes, you must make to make this script running in german environments:

      To all who want to use this script with different language-Exchange-Servers:

      Regarding the errors on Exchange-Server in other languages:

      You have to change the lines 346-349, where there are only the english server-role-names.
      In the output with the error-messages, you can see the name of the roles in your own language, e.g in german:
      “Hub-Transport-Serverrolle Services: Pass
      Add-Member : Das Argument kann nicht an den Parameter “Name” gebunden werden, da es NULL ist….”

      So you must change (or add lines) e.g. on german exchange-server:

      “Clientzugriff-Serverrolle” { $roleservices = “CA Services” }
      “Hub-Transport-Serverrolle” { $roleservices = “HT Services” }
      “Mailbox-Serverrolle” { $roleservices = “MB Services” }
      “Unified-Messaging-Serverrolle” { $roleservices = “UM Services” }

      instead of(or additional to):
      “Client Access Server Role” { $roleservices = “CA Services” }
      “Hub Transport Server Role” { $roleservices = “HT Services” }
      “Mailbox Server Role” { $roleservices = “MB Services” }
      “Unified Messaging Server Role” { $roleservices = “UM Services” }

      Additionally you must change the following line:
      if ($testmailflowresult -eq “Success”)

      to your own language, e.g. on german Exchange Server:
      if ($testmailflowresult -eq “Erfolgreich”).

      You can find the correct word of your language also in the output before you have fixed it:

      Public Folder databases mounted: Pass
      Mailbox databases mounted: Pass
      MAPI connectivity: Pass
      Mail flow test: Erfolgreich

      After these changes the script works fine for my german exchange organisation

    • Update because of newer Version of Script:
      I have added/changed the following line on a german Exchange Server:

      Line 446:
      I added 4 lines:
      “Clientzugriff-Serverrolle” { $serverinfoservices = “Client Access Server Role Services” }
      “Hub-Transport-Serverrolle” { $serverinfoservices = “Hub Transport Server Role Services” }
      “Mailbox-Serverrolle” { $serverinfoservices = “Mailbox Server Role Services” }
      “Unified-Messaging-Serverrolle” { $serverinfoservices = “Unified Messaging Server Role Services” }

      After that I changes line 604 to:
      if (($mapiresult -ne “Success”) -and ($mapiresult -ne “Erfolgreich”))

      and I changed line 651 to:
      if (($testmailflowresult -eq “Success”) -or ($testmailflowresult -eq “Erfolgreich”))

      I don’t have DAG in my environments, could anyone, who has DAG and german (or other not-english exchange-server) please test, what happens with the DAG-Check?

  94. Paul,

    regarding “Healthy Queues” in the script, i can’t not really figure out, what that should mean. (and I also get a warning with a “2″ in the field)
    Can you explain the test in a few words?

    Thanks

    • Each database copy has a copy/replay queue for replication. An unhealth queue is one that has more logs in the copy/replay queues than the $replqueuewarning is set to (which I set to 8, but you can adjust it higher if you want to).

      Healthy Queues will be yellow (warning) if the number of healthy queues is less than the total number of queues.

      In other words, if you’ve got 3 copies of a database, and all three copies have healthy queues, then “Health Queues” will be green. If only two of the copies have health queues, then “Healthy Queues” will be yellow.

  95. Paul, I can’t seem to get this working in Exchange 2007, I have modified it to use the correct 2007 powershell plugin, and setup smtp settings correctly. However, when I run the script it gets past checking server roles, then closes the powershell window (crashes) with no errors that I see.

    • Sanjeev says:

      I am also facing the same problem in Exchange 2007 environment. Looking at previous comment from the people regarding Exchange 2007, it seems the older version of the script works fine for Exchange 2007.

      Paul, Can we have the older version of this script? :)

      • Figured I would reply so others could fix it in 2007. I got it working using the following old script on 2007, just change the 2010 plugin to the 2007 plugin, comment out the 2010 Get-AD stuff, and add-in your smtp settings and you’re done.

        http://dl.dropboxusercontent.com/u/13009245/facility.net/Test-ExchangeServerHealth.ps1

        Also if anyone wants to setup scheduled task for this I got it working as well by created a batch file with the following code:

        powershell.exe -command “. C:\Scripts\ExchangeServerHealth\Test-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

  96. Have you considered adding transaction log stats?
    Something line http://www.exchangebytes.com/?p=301

Leave a Comment

*

We are an Authorized DigiCert™ SSL Partner.
Loading...

Still running Exchange 2003? Time to get moving and start your upgrade. Find out how - Click Here