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

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:

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

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

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.

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.

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

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?

Feedback and suggestions are always welcome. And of course you are encouraged to customize the script to suit your own needs as well.

Paul is a Microsoft MVP for Office Servers and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul is a co-author of Office 365 for IT Pros and several other books, and is also a Pluralsight author.
Category: Exchange Server

809 comments

  1. Philip says:

    When I run this script i get this error:

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

    Please help me correct this.

    Regards

    Philip

  2. Philip says:

    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.

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

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

  4. Ray says:

    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.

        • Andy Helsby says:

          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

      • Arras says:

        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

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

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

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

    • shiraz says:

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

      Thanks it works for me

    • Mohamed Ramadan says:

      I can’t find this line to add to the script!
      Could any one inform which line is it?
      Thanks

  7. Simon says:

    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 🙂

  8. SamuelZ. says:

    Hi Paul!!

    I’m having this problem.

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

      • EricLemay says:

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

        Thank you.

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

      • Rene Joram says:

        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

  9. Gemmy says:

    Dear Paul,

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

    C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -command “. ‘C:Program FilesMicrosoftExchange ServerbinRemoteExchange.ps1’; Connect-ExchangeServer -auto; F:PSScriptTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

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

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

    Cheers 🙂

  10. Ed says:

    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 🙂

      • Ed says:

        Hi Paul, Thanks for getting back.

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

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

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

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

    • 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

  11. Kerry Denten says:

    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

      • Kerry Denten says:

        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?

      • Kerry Denten says:

        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.

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

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

          • Matt D says:

            Hi Paul – I’m after something similar with the opposite of the ignore list – the latest version of your script references this a servierlist but doesn’t have any line that references what the file is called or where it is located in the same way the ignore list was. Thanks, Matt

          • You can use -ServerList and then specify the name of the file containing your list of Exchange servers. You have to provide the name of the file, the script won’t go looking for a specific file name by default.

            The one caveat is that if you use -ServerList the DAG checks are skipped. That isn’t ideal for everyone, I know, but it’s a carry over from legacy code.

    • 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:TempTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:262 char:18
      + [int]$uptime <<<< = "{0:N0}" -f $uptime
      + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
      + FullyQualifiedErrorId : RuntimeException

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

  13. 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:TempTest-ExchangeServerHealth.ps1:261 char:18
    + [int]$uptime <<<< = "{0:N0}" -f $uptime
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

  14. Rafi says:

    Hi, Great script, thanks a lot.

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

    Regards,
    Rafi.

  15. Rafi says:

    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.

  16. 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:TempTest-ExchangeServerHealthTest-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.

  17. Marco says:

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

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

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

    BRGDS
    Marco

    • Marco says:

      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

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

  19. shc says:

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

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

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

    • Jan Kovar says:

      Hello Paul.

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

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

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

      BR
      Jan

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

  21. Vann says:

    Hi Paul,

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

    I’m running this directly on the exchange server.

    Here is the error I get.

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

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

  22. 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:********ToolsTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:683 char:19
    + $hours = [int] <<<< $($reportline."uptime (hrs)")
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

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

  23. 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:windowstempreport.csv -Force -NoType

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

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

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

      • Kerry Denten says:

        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

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

        • Kerry Denten says:

          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.

        • Marc Kean says:

          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.

  25. LeeH says:

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

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

      • Carlos says:

        Hi Paul,

        Many thanks – your script is a life-saver!!
        However, I am having similar issues with the Mail Flow Test.
        We have an Exchange 2013 environment. I am running the script in a scheduled task with the argument below:
        Powershell -executionpolicy bypass -file C:1ScriptTest-ExchangeServerHealthSW.ps1 -Log -SendEmail

        The report that gets mailed always shows that “mail flow test failed” on both my exchange servers. If I directly run the same command in Powershell or via Start > Run, I get a Pass for all the tests.

        I had a look at the Log generated, and the one line in there says “11/30/2015 13:45:03 The term ‘Test-Mailflow’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
        11/30/2015 13:45:03 Mail flow status is Fail”

        Please help when you can, I have no clue what’s going on.
        Thank you,

  26. Henry says:

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

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

  28. Sean says:

    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

  29. Alex says:

    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

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

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

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

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

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

  35. Elio @TW says:

    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.

  36. Fredo says:

    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 🙂

    • Bikram says:

      I second this request as this is a major concern… Hard Disk getting full and not aware of this can and has created havoc many times…

      Is there a way to add HDD consumption/ free/ space data into these reports.

      Thanks for such awesome efforts & script… gives insight and foresight of exchange environment

      Thanks,

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

  38. Paul L says:

    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

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

  40. amit says:

    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

  41. Oleg A says:

    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.

  42. James Mc says:

    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

  43. Nick says:

    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

  44. Paul says:

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

  45. Tom says:

    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

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

  47. Tom Major says:

    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

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

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

  50. Ed says:

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

  51. PaulR says:

    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

  52. Ross says:

    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?

    • Ross says:

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

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

      • Ross says:

        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 —

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

  54. 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: 0x80010002 (RPC_E_CALL_CANCELED))”

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

  55. Feroz says:

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

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

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

  56. Stephen says:

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

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

  58. Tim says:

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

  59. Kirill says:

    Helllo, thank you, but need some help.

    I getting this error

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

    Mailbox databases mounted: Pass
    MAPI connectivity: Pass

    • Rene Joram says:

      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

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

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

  62. Mike says:

    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

      • Mike says:

        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?

  63. Bhushan says:

    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.

  64. Lee says:

    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!

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

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

  66. Skye says:

    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!

  67. Rene Joram says:

    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

  68. Flo says:

    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

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

  70. Kerry Denten says:

    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 🙂

  71. Asif says:

    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

  72. 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:ScriptTest-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:ScriptTest-ExchangeServerHealthTest-ExchangeServerHealth.ps1:880 char:47
      + $memberObj | Add-Member NoteProperty -Name <<<< $($healthitem.Check) -Value $($healthitem.Result)
      + CategoryInfo : InvalidData: (:) [Add-Member], ParameterBindingValidationException
      + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
      mmand

      Thanks a lot

      • kwannapa says:

        [PS] D:ScriptTest-ExchangeServerHealth>.Test-ExchangeServerHealth.ps1

        This is command i ran it.

        Thank for your quickly answer

        • kwannapa says:

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

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

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

  74. Michael Roth says:

    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.

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

    • Rene Joram says:

      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

    • Rene Joram says:

      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?

  76. Flo says:

    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.

  77. Wooten says:

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

      • Wooten says:

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

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

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

        powershell.exe -command “. C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

        • Sanjeev says:

          Thanks Wooten. That worked for me 🙂 . Just want to check if this test runs HT Services and Transport queue for Edge Server as well. Or As Edge server is in DMZ, Do we need to open some ports to make this work?

  78. Tony Holdgate says:

    HI Paul,
    We have 5 edge servers that I need to include for testing. I note in the script you say
    “If you want to include then, remove this If.”

    Being nowhere close to your skill level could you qualify the line numbers to remove? 409-423?

    Finally it would be great if there was a disk space check in there but that a nice to have only
    Thanks
    Tony

    • Thanks for the suggestions. Since Edge is apparently here to stay in 2013 I have it on my list to add in some checks for that role.

      I agree, disk space would be handy as well. Its on the list.

      • Tony Holdgate says:

        HI Paul,
        One more thing- Public Folder databases and replicas check? Might be a tough one. I know you test the services but is anything more possible?

  79. Jeff St. Louis says:

    Hi Paul,

    First things first, just wanted to let you know this is a great little script.

    I am having a small issue, I cannot seem to run the script using the Task Scheduler. It appears to run fine (no errors) but the html report doesn’t generate and I don’t receive an email.

    When I run it from the command line, it works great every time. The report gets generated and I receive a nice email.

    I’ve followed your instructions, plus I’ve adjusted the arguments and called the full path of the powershell command itself, but still no go.

    Have you heard of anybody else having this trouble, or am I the lucky one? Windows Server 2008R2 Enterprise, with Exchange 2010 SP3.

    Any tips or insight would be much appreciated! Thanks

    • Shane Bryan says:

      Hi Jeff, I have it working in my environment via Task Scheduler. If you want to compare task settings maybe I can help.

      • Shane Bryan says:

        For the record my settings are;

        General tab: run logged in or not, with highest privileges. Configure for 2008R2.
        Triggers tab: irrelevant, whatever schedule you want.
        Actions: Start a program: powershell.exe

        the command I have appended to it is;

        -command “. ‘C:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1’; Connect-ExchangeServer -auto; c:PsscriptsGet-MailboxReport.ps1 -all”

        The remaining tabs, conditions, settings & history shouldn’t impact on it, but I also have the option to allow it to be ran on demand.

        if you want a screengrab, please let me know. obviously i’ve made the changes in the script where needed for mail server etc etc.

        Cheers, Shane.

        • Shane Bryan says:

          ahh sorry, wrong script. here’s the command i’m using.

          Actions – start a program – powershell.exe

          -command “. ‘C:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1’; Connect-ExchangeServer -auto; c:PsscriptsGet-DAGHealth.ps1 -detailed -sendemail”

        • The latest version doesn’t need all that in the command. The settings I use are in the blog post above the bug list/FAQ bit at the end.

          Jeff, I’d suggest testing your Task Scheduler command in a cmd.exe window. See if that shows any errors (which will be a clue) or if it works fine (which will indicate that something in Task Scheduler is not right).

  80. Jeff St. Louis says:

    Here’s what I get when i run it from the command line!

    C:Usersexchadmin>powershell.exe -command “E:PowerShellScriptsExchangeServerH
    ealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail”
    E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 : A par
    ameter cannot be found that matches parameter name ‘sendemail”‘.
    At line:1 char:96
    + E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -repo
    rtmode -sendemail” <<<<
    + CategoryInfo : InvalidArgument: (:) [Test-ExchangeServerHealth.
    ps1], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Test-ExchangeServerHealth
    .ps1

  81. Jeff St. Louis says:

    Hi Again,

    Just triple checked.

    If I run the following command in the command prompt (cmd.exe) it does not work and throws the error I posted earlier.

    If I run it from the powershell (fresh, just open and run) it works like it should.

    powershell.exe -command “E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail”

    It doesn’t like the “sendemail” parameter for some reason

  82. Jeff St. Louis says:

    Figured it out… Both the command prompt (cmd.exe) and the Task Scheduler do NOT like the quotes around the command.

    powershell.exe -command E:PowerShellScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode -sendemail

    Strip them off, and voila. It’s working!

    Thank-you for your help

  83. Clint Swiney says:

    Paul! AWESOME script made even better. You ROCK!

    We have a Lagged DAG in a separate Data Center which was causing failures when performing the Test-ReplicationHealth check, specifically the DBLogReplayKeepingUp health check. In order to repair I created a new variable:

    $transientevsupptimeout = 5 #Change to set the TransientEventSuppressionWindow in minutes for test-replicationhealth

    Then modified line (876 in the original script):

    $replicationhealth = $dagmember | Invoke-Command {Test-ReplicationHealth -TransientEventSuppressionWindow $transientevsupptimeout}

    This reduces the number of failures due to transient load generation.

    http://technet.microsoft.com/en-us/library/bb691314(v=exchg.141).aspx

    Now the script runs error free.

  84. Kerry Denten says:

    G’day Paul,

    In the earlier versions of this script, it didn’t seem to cope well if it had been run more than once within a short amount of time.

    With that in mind, can this new version of the script be run at the exact same time on two separate nodes?

    Y’see, we have the script in place and fully configured to run on two of our HUB nodes, so that if one has a Transport failure, at least we’re still able to get reports and/or alerts from an alternative node with accurate health information.

    What I want to do is set up the “alerts” version of the script to run to the exact same schedule on two nodes every ten minutes.

    Then I want the “health report ” version to run to a staggered schedule across both nodes, thus delivering health reports every three hours from a different node each time.

    But what I don’t want to do is lull myself into a sense of false security thinking the alert scripts are happliy running every ten minutes, when in fact they’re failing, because I’m trying to run them simultaneously.

    I’ve run some tests, and the scripts seems to be coping with running simultaneously on two nodes, but I just thought it wise to check.

    Kerry

  85. Tony Holdgate says:

    We had an issue last night where our deployment scripts failed to set the http redirect for OWA for some new CAS servers we built. Is there a way to build this into the next version?
    CHeers
    Tony

  86. bounce813 says:

    Paul, Your script is an amazing tool. I would like to send a copy of the HTML report to Share Point instead of the default location. Could you tell me where to set an alternate directory?

    Thank you!

  87. Sergey says:

    Hi,

    Nice script!!
    But could you please clarify what does mean status:
    – Mailbox Server Role required services not running.
    – Client Access Server Role required services not running.
    – Hub Transport Server Role required services not running.
    For one of the node in DAG cluster. Cluster is up and running. What should I check in this case?

    Thank you!

  88. Ziemek Borowski says:

    Hi,
    First – thank for that script. Extremly usefull. 🙂

    When I call that script from another (to get any “documentation snapshot” of env) I receive something like that:
    —- Database Copy Health Summary —-
    out-lineoutput : The object of type “Microsoft.PowerShell.Commands.Internal.Format.FormatStartData” is not valid or not in the correct sequence. This is likely caused by a user-sp
    ecified “format-table” command which is conflicting with the default formatting.
    + CategoryInfo : InvalidData: (:) [out-lineoutput], InvalidOperationException
    + FullyQualifiedErrorId : ConsoleLineOutputOutOfSequencePacket,Microsoft.PowerShell.Commands.OutLineOutputCommand

    In script before call Test-ExchangeServerHealth.ps1 I’ve only mkdir $repdir.
    Have You any idea how to fix it?
    Temporary workaourd (which works) is call Test-ExchangeServerHealth.ps1 into variable (also call mkdir into variable works). Or modify 6 lines starting from $dagdatabasesummary | ft (ie. by remove ft or comment that output — which is aceptable if we execute it for HTML/mail report).

    But it’s quite annoying. 🙂

  89. Hayley Heskiel says:

    Hi! First I’d like to say this script looks fantastic and I’d love to get it running. Can this script work in a Exchange 2007 only environment?

    We have a CCR and 2 HT/CAS/MBX servers, and another CAS
    When I attempt to run it, I get the following:

    —— Checking EXCHE
    DNS Check: Pass
    Server up: Pass
    Uptime (hrs): 352
    Server version: Exchange 2007
    Roles: Mailbox, Client Access, HubTransport

    Then it pauses there for a moment and the window just closes. This happens in Powershell, Exchange Management Shell, or Powershell Editor. I can’t seem to find why it’s closing and if it’s an error in the script or something else. Any help would be greatly appreciated.

    Thank you!

    • Sanjeev says:

      Hello Hayley,
      Wooten mentioned

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

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

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

      powershell.exe -command “. C:ScriptsExchangeServerHealthTest-ExchangeServerHealth.ps1 -reportmode $true -sendemail $true”

      btw, We are working to add “Test-OWAConnectivity” and ‘Test-Activesyncconnectivity” tests as well to the script for Exchange 2007. I’ll share it once completed.

      • Hayley Heskiel says:

        Hi Sanjeev,

        I figured out the exact area that was causing that issue. I’d already changed the snapping to be for 2007. The section that runs the ping check apparently crashes the script. I don’t know why, but as soon as I removed the section, the script ran flawlessly. I left in the part about new object and the write host for a pass. This way it just registers the ping as a pass and moves on. If the servers aren’t pinging, I’ll know about it before then. It has to be in the script or the report ends up being skewed. Thank you for your help!

  90. Sushant says:

    Hi Paul,

    Currently we are running same script to export health of our exchange servers, Script is working ok..

    thanks for nice work.

    But My question is that can we exclude Database name instead of server name.?

    I am just checking if you have any alternate way to do this please help me.

    Thanks,
    Sushant

  91. Anant says:

    Hi Paul,

    Thank you for the script. It is working fine.
    I just wanted to add two more colums LatestFullBackupTime and LatestIncrementalBackupTime

    I tried hard but no luck.(I dont have much idea about scripting)

    Could you please suggest

    Thanks in advance

    Anant

  92. Rhys says:

    Heya Paul,
    thanks for the script – nice work.

    Just one issue. I’ve had v1.1 working fine and have now upgraded to v1.2. Strangely enough I’m wrestling with permissions issues now. I am running with a domain service account which has “log on as a batch job” to the local server. However it refuses to run unless I make it a local Administrator of the machine. The task does not error, it just runs perpetually.

    If I remove the following line, it works (but then does not report on any DAG checks):
    . $env:ExchangeInstallPathbinRemoteExchange.ps1

    Any suggestions? (Exchange 2010)

    Cheers,
    Rhys

  93. sajeev says:

    Hi Paul,
    the script working fine. I’m trying to run this script in my task scheduler with a service account which have minimum priviliage on the server. For example, i want the service account able to complete the test and send the report out but unable to make any changes to Exchange or server and reboot/shutdown server. Do you have any suggestion on which kind of membership I should give to the service account ?

  94. Pradeep says:

    Hi Paul,

    thank you for the great script.

    I am facing a strange issue here. When I run the script , no matter if i use server, server list or no parameter at all…. After displaying status of servers in my site, it automatically starts checking the servers in a remote site, which I obviously dont want to do. Could you please let me know what could be triggering this?

    Also, I used ignorelist parameter as well . but it didnt work.

    This is causing my script to pause for good 5 mins before displaying error that cannot connect to those servers.

    Any help would be much appreciated. Thanks

    • You can set mutliple recipients in the SMTP config in the script separating them with a comma.

      To = “email1@domain.com”,”email2@domain.com”

      Or just put a single address that goes to a distribution list.

      • Marcus says:

        Paul,
        I’ve tried what you’ve suggested and that does not work for me, it only sends to the first email address. Could you help out?

        Thanks

  95. Rosario says:

    I might be a bit late, but I just integrated some new figures into the script:

    – local Drives: Capacity, Used, Free Space

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

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

    Paul, thanks a lot, I learned a lot, Rosario

  96. Kelley says:

    I’ve been running the script for a while now and love the latest version. I recently changed nics in my server to vmxnet 3 and they all seem to be running fine. When I run the script at the command prompt all servers tests pass as well as the DAG tests. When I run it as a scheduled task and send email I get the following error on one of the HT/CAS boxes: “Could not test service health”. This occurs in all four columns regarding roles. Any idea why?

    Both tests, command line and scheduled, report that the cluster network for each of my three mailbox servers has failed. However, the cluster appears fine in the console and databases can be moved at will. Any idea why this would be marked as failed?

  97. Kelley says:

    I found the cluster problem. It was a rogue network with only IPv6 addresses created by the new NICs before addressing. The other issue is a DNS problem where the A record is disappearing. I really appreciate this script and all the other things you do for the Exchange community.

  98. Rance says:

    Is there any way to remove a specific role from the list. We dont have any Unified Messaging Servers in our org and I’d like to remove it from the report.

  99. sounder says:

    Hello Paul,

    We have 6 exchange servers in the same site with typical exchange installation i.e. Hub, ,Mailbox and CAS.

    For Example below are the exchange servers:

    mailmxexch01
    mailmxexch02
    mailmxexch03
    mailmxexch04
    mailmxexch05
    mailmxexch06

    i ran the below script on mailmxexch06 exchange server

    .Test-ExchangeHealth2.ps1 –reportmode $true –reportfile ServiceHealthStatus.html

    result is generated in ServiceHealthStatus.html file .

    My question 1 : If i run the above mentioned script on mailmxexch06 exchange server , what will be the source server for mail flow?

    IF the source server is mailmxech06 (where i am executing the script) then what will be the sending email addres and recipient email address for the mail flow test?

    My second question 2: is this script is for both inbound mail flow test as well as for outbound mailflow test? OR this test only for outbound? .

    Question 3: How is the test for the mailflow performed?

    protocol logging is enabled on the above all 6 servers , i didnt found any SMTP Send OR Recieve logs?

    Question 4: To send a test email from source server to target server , we need sender and recipient email address right? what wll be the sender/recipient email addresses in the above script?

    please suggest me.

  100. Aidan says:

    Hi Paul,

    Whats the best way to exclude the Edgetransport service from being listed your array ? I love the script but dont want to start sending it to my team with big red markers saying service Failure when we arent using it 🙂

    P.S. I have zero powershell experience but getting into thanks to this 🙂

    Appreciate any help!!!

    Kind regards,
    Aidan

      • Aidan says:

        Hi Paul,

        You are correct but the service will not start as we are not using it. I can see in your other article relating to the event ID 1045 (which I receive when trying to start it) the solution is to create the configuration object New-EdgeSyncServiceConfig -Site “my site”

        Are there any implications to be aware of or prior criteria?

        Appreciate the help!!

        Kind regards,
        Aidan

        • Aidan says:

          I should also probably mention its a 2 CAS and 2 DAG server array we use with cisco ironports in front to handle antispam etc..

  101. Doug says:

    Love the script. Love seeing all of the GREEN font. However, I received one big red FAILURE on one test on one of the servers. It was the test-mailflow cmd. Everything else was green. All services were running. Test-MAPIConnectivity. But not test-mailflow. Test-mailflow from other server, even in the other datacenter, to the subject servers succeeds. But test-mailflow from the subject server, even to itself. I can’t find much on troubleshooting this event. Do you have any suggestions? Can the system mailbox be reset somehow? I’m at a loss as to how to best deal with this failure.

    Thanks

    • Doug says:

      Never mind. Found it. Turned out to be a duplicate system mailbox in AD. Had the same GUID, but was appended with “CNF:” and another GUID. Microsoft said it was near impossible for this situation to occur. Guess I just got lucky. I deleted the duplicate System mailbox. All is good now. Thanks.

  102. Paul B says:

    Paul, thanks for your effort in producing this script, I enjoyed seeing Green across the board! 🙂
    Brilliant job and very much appreciated!

  103. Sanju says:

    Hi Paul,

    I was modifying the Script and want to add RPC connection test.

    # Start RPC Connections Test

    if ($IsCAS)
    {

    $RPC = $null
    $RPC = Get-Counter “MSExchange RPCClientAccessConnection Count” | select -expandproperty CounterSamples | select CookedValue
    $serverObj | Add-Member NoteProperty -Name “RPC Connections” -Value $RPC -Force
    if ($Log) {Write-Logfile “RPC Connections is $RPC”}
    }

    #END – RPC Connections Test

    However the above does not works and errors out

  104. christian says:

    Hi,
    Don’t know what I am doing wrong but I don’t get any html output, if I export it to an html file it opens an empty web file. I tried both via the command line and task sceduler. the email is beeing send to me but I only see; “Exchange Server Database Availability Group health check results as of dinsdag 27 augustus 2013 17:14:12”

    Only thing I changed are the mailsettings.

    Anybody a clue?

    Command; -command c:scriptsGet-DAGHealth.ps1 -detailed -sendemail

    I run it from my only exch2010 server.

  105. Tony Holdgate says:

    W’ve been using this for some months now- great script. We had an issue over the weekend where a mailbox server manually had the exchange services stopped and then was shutdown. However the windows failover clustering service was not stopped and (I think) because the server was shutdown before this service realised the services were gone, the failover did not happen.

    What this made us realise is that even though clustering is a windows server service- its a fairly critical part of a DAG and it would be nice to monitor the service’s availability. Practical or a folly?

    • Shane Bryan says:

      We monitor that, but in real-time as part of our network monitoring setup. We only run this script in the morning, as Paul says – to identify overnight issues – and then once more in the afternoon.

      If key windows services fail on a server, we prefer to know about it immediately rather than waiting for the scheduled task running this (awesome) script.

      (we’re using IPMonitor from Solarwinds).

      Cheers Shane.

      • Tony Holdgate says:

        yep we should be doing that also….but working in a govt dept these things take too long. So we tend to monitor our own to make sure. However I’m putting the request in with the relevant area

  106. Erik J says:

    When running the script with modifyed smtp settings i get this:

    Send-MailMessage : The specified string is not in the form required for an e-mail address.
    At C:ScriptTest-ExchangeServerHealth.ps1:1825 char:20
    + Send-MailMessage <<<< @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF
    8)
    + CategoryInfo : InvalidType: (Exchange server ADMIN:String) [Send-MailMessage], FormatException
    + FullyQualifiedErrorId : FormatException,Microsoft.PowerShell.Commands.SendMailMessage

  107. Erik J says:

    I get one more error, thats I (who is a beginner on this) dosent understand:

    This I get when i start the script:

    [PS] C:Script>.Test-ExchangeServerHealth.ps1 -Log -SendEmail
    Initializing…
    Update-TypeData : The following error occurred while loading the extended type data file:
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binexchange.types.ps1xml : File skipped because i
    t was already present from “Microsoft.PowerShell”.
    At D:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1:94 char:17
    + Update-TypeData <<<< -PrependPath $typeFilePath
    + CategoryInfo : InvalidOperation: (:) [Update-TypeData], RuntimeException
    + FullyQualifiedErrorId : TypesXmlUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand

    Update-TypeData : The following error occurred while loading the extended type data file:
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binExchange.partial.Types.ps1xml : File skipped b
    ecause it was already present from "Microsoft.PowerShell".
    Microsoft.PowerShell, D:Program FilesMicrosoftExchange ServerV14binexchange.types.ps1xml : File skipped because i
    t was already present from "Microsoft.PowerShell".
    At D:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1:104 char:16
    + Update-TypeData <<<< -PrependPath $partialTypeFile
    + CategoryInfo : InvalidOperation: (:) [Update-TypeData], RuntimeException
    + FullyQualifiedErrorId : TypesXmlUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand

  108. Ray Cockshell says:

    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

  109. Andrew says:

    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

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

      • Sathya Paul says:

        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
        }

        • 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

  110. Vidya Sagar says:

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

  111. Atul Mangla says:

    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

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

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

      • Rosario says:

        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

  114. Khalid says:

    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

  115. Phil Smith says:

    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.

  116. OzDM says:

    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.

  117. Henrik says:

    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

  118. Andrey Ganimedov says:

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

    • Rosario says:

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

  119. Noor says:

    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.

  120. Andre Winkler says:

    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.

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

    • Andre Winkler says:

      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é

      • Rosario says:

        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

        • Andre Winkler says:

          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é

  121. Richard says:

    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?

  122. Jackson says:

    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

  123. martinezjrj says:

    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

      • martinezjrj says:

        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

  124. martinezjrj says:

    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

  125. Michael Wiskman says:

    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.

  126. Rob says:

    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.

  127. Jose Byron Gonzalez says:

    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!

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

  128. Jimmy Singal says:

    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.

    • Aidan says:

      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

      • Jimmy Singal says:

        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.

        • Aidan says:

          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!

        • Rosario says:

          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

        • Jimmy Singal says:

          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.

        • Rosario says:

          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

  129. Aidan says:

    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!

  130. André Winkler says:

    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.

    • André Winkler says:

      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é

      • Rosario says:

        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

  131. Gary Libero says:

    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

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

      • Gary Libero says:

        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

  132. Jeromy Baldridge says:

    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.

  133. Vishal Patel says:

    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.

  134. June Castillote says:

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

  135. Pär Glanzén says:

    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?

  136. Juanita says:

    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

  137. Andy says:

    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

  138. Gabe Foltz says:

    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

  139. Adam Borders says:

    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

  140. Amar Kanta says:

    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

  141. Mustafa Zain says:

    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,

  142. Nikolas says:

    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?

    • Nikolas says:

      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?

        • Nikolas says:

          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.

        • 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

  143. Damian says:

    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.

  144. Adam Borders says:

    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.

  145. Mohamed Salama says:

    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?

  146. Prakash says:

    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

  147. Peter says:

    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!

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

  148. George says:

    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

  149. Mike says:

    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

  150. IT says:

    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.

      • IT says:

        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.

        • IT says:

          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)

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

  151. Phil says:

    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?

  152. Erik says:

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

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

  153. Nick Paolini says:

    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

  154. shanif says:

    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

  155. Matt says:

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

  156. Anthony says:

    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?

  157. Doug says:

    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.

  158. Tim Klassen says:

    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!

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

  159. Alexis Crawford says:

    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?

  160. Mohamed Ramadan says:

    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?

    • Mohamed Ramadan says:

      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’

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

  161. SysAdmin says:

    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

  162. Rich says:

    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.

  163. Essexboy says:

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

  164. Admin says:

    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.

  165. Gregory says:

    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

  166. Chretien says:

    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

  167. Paul says:

    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?

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

  168. Chretien says:

    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

  169. Chretien says:

    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

      • Chretien says:

        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

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

  170. Harish Bajaj says:

    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.

  171. Frank says:

    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

  172. Tausif says:

    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

  173. Gabe Foltz says:

    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?

  174. Gabe Foltz says:

    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.

  175. Sachin ladde says:

    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.

  176. Shahid says:

    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

  177. NashTek says:

    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

  178. Shahid says:

    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.

  179. Shahid says:

    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.

  180. Kristijan says:

    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

  181. Kristijan says:

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

    Thnx & regards!

  182. Steven says:

    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.

  183. Jijo Antony says:

    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.

  184. Carlos Rotver says:

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

  185. Krishna says:

    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.

      • Krishna says:

        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.

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

  186. Rob Derbyshire says:

    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

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

      • Brian says:

        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

          • Matthew McDonald says:

            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:

          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.

  187. Lucas Falconi says:

    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 ?

  188. Manfred Paleit says:

    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.

  189. Niclas Johansson says:

    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.

  190. Manfred Paleit says:

    for a simple sort of Servers …

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

    foreach ($server in $exchangeservers) ….

  191. Raj says:

    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 ?

  192. Sanat says:

    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.

  193. John says:

    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.

  194. Matt says:

    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

  195. HerbZ says:

    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

  196. Jack Chuong says:

    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.

  197. Chris says:

    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?

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

      • Chris says:

        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!

  198. Kapil K says:

    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

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

  199. Paul says:

    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

  200. Mukhan says:

    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.

  201. Glen says:

    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