Steve Goodman's Exchange Blog
17Jun/11246

Generate Exchange Environment Reports using Powershell

imageUpdate 17th August - V1.5.4 - New features and bug fixes (see here for more information)

Update 24th July - V1.5.3 - Bug fixes (see here for more information)

Update 21th July - V1.5 - Re-write with new features including Exchange 2003 support for mixed environments and more detailed information (see here for more information)

Update 21th June - V1.1 - Bug fixes, Exchange 2007-only support in addition to 2010/2010+2007, and new features.

As an Exchange administrator, there’s times when it’s useful to have a visual, straightforward and concise document that gives you a good overview of your environment. Although with tools like Visio and Word you can make such a document, it’s hard to keep these documents up to date or use previous versions to track and check changes.

This script, inspired by the output of an Exchange TAP tool, aims to automatically generate a report that gives you an overview of your environment, Exchange 2003, 2007, 2010 servers and database availability groups - in particular:

  • Total Servers per Exchange version & service pack
  • Total Mailboxes per Exchange version & service pack
  • Totals for Exchange roles across the environment
  • A site-by-site breakdown for the following:
    • Mailboxes per site
    • Exchange servers, version, update rollup  and version, service level, highlighted installed roles, OS version and service pack
  • A breakdown of each Database Availability Group including:
    • DAG name, member count and member list
    • Database information such as
      • Name
      • Mailboxes per database and Average Size
      • Archive mailboxes per database and Average Size - only shown if a DB includes Archive mailboxes
      • Database and whitespace size
      • Database and log disk free space percentage
      • Last full backup date/time (new) - only shown if at least one DAG DB has had a full backup
      • Circular Logging state (new) - only shown if at least one DAG DB has circular logging enabled
      • Server hosting the active copy
      • List of servers hosting copies and copy count
  • A breakdown of Non-DAG databases including Exchange 2007 and 2003 DBs, including the database information above, along with Storage Group name (where applicable).

The script doesn’t support detailed information about Exchange 2007/2003 CCR/SCC clusters, but these are shown as ClusMBX in the output. At the moment, the script doesn’t show Public Folder information but if there is interest I can add extra features; and of course the source is provided should you wish to alter it to your own needs.

To be able to execute the script, you need to use the Exchange Management Shell (the latest version for your environment, with Powershell 2.0) and be able to get information about AD Sites, Exchange Servers, Mailboxes, Database Availability Groups and Databases. It uses WMI to retrieve OS information and detect Exchange 2007 clusters and calculate Exchange 2007 database size and Remote Registy calls to get Update Rollup information. A normal Exchange administrator should be able to perform these tasks.

Executing the script is straightforward – the only setting you need is to specify where to write the HTML file:


GeSHi Error: GeSHi could not find the language powershell (using path /home/content/03/9366303/html/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

If you want it to email the results, the follow parameters are available to allow the report to be sent directly from the script:


GeSHi Error: GeSHi could not find the language powershell (using path /home/content/03/9366303/html/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

Finally,  to schedule the report to be generated nightly, execute with your preferred options and add the -ScheduleAs parameter, for example:


GeSHi Error: GeSHi could not find the language powershell (using path /home/content/03/9366303/html/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

After generating the report, it will attempt to schedule the task and prompt (via schtasks.exe) for the password of the user you have chosen to schedule the report as.

As usual, the script is provided below as-is without any warranties. You can download the script ready to use at the bottom of this post. Comments and suggestions are always welcome.


GeSHi Error: GeSHi could not find the language powershell (using path /home/content/03/9366303/html/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

Download Get-ExchangeEnvironmentReport.ps1

Looking for the previous version? Download version 1.1 here

Related posts:

  1. V1.1 of Exchange Environment Report script available now
  2. Exchange Environment Report 1.5.3 released
  3. Exchange Environment Report Script V1.5 available
  4. Exchange Environment Report v1.5.4
  5. How to report which Exchange mailboxes group members have full access to

Posted by Steve Goodman

Comments (246) Trackbacks (24)
  1. Thank you for your great script, it saved me a lot of work!

    Every time I’m running your script using the parameter –ServerFilter I get a mailbox count of zero. I looked in your script and changed in sections 2.1 every appearance of “Where {$_.Server -like $ServerFilter}” to “Where {$_.Servername -like $ServerFilter}”. Now mailbox counts are correct.
    As we have a pure Exchange 2007 environment, I can’t tell if the problem exists for Exchange 2003 and 2010.

  2. Hi Man!

    Great Script. Is there a way that it can be sent to more than 1 recipient?

  3. Hi,

    THANKS for writing this, it does save a lot of time!! I have a question. I have a small Exchange 2007 environment, and it isnt reporting the white space properly. I see plenty of 1221 event ID’s with the proper data in the event viewer. any ideas?

    Thanks!

  4. Hi Steve,

    Great script. I have an addition to the wish list. – Last Incremental Backup column

    Thanks

  5. Hi Steve,

    i believe this script could be very usefull for mr , but while i am trying to run this script it is showing me the below error , could you please help me out in this..

    File D:\Power shell 2.0\Script\Get-ExchangeEnvironmentReport.ps1 cannot be load
    ed. The file D:\Power shell 2.0\Script\Get-ExchangeEnvironmentReport.ps1 is not
    digitally signed. The script will not execute on the system. Please see “get-h
    elp about_signing” for more details..
    At line:1 char:2
    + . <<<< '.\Get-ExchangeEnvironmentReport.ps1'
    + CategoryInfo : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

    Thanks

    • Run Get-ExecutionPolicy.

      If it is set to Restricted, change it to RemoteSigned or Unrestricted.
      If it is set to RemoteSigned, move the script to a local drive or change it to Unrestricted.

      To change the execution policy, use Set-ExecutionPolicy.

  6. Hi, we use this report tool too, very useful.
    Unfortunately, in our exchange environment the Database instances are not sorted alphabetically.

    Any Ideas?

    MAN-EXCH-001 DB_K 82 1,163.78 MB 107.01 GB 0.44 GB 32.81 GB 22.0% 32.81 GB 22.0% Yes (1)
    MAN-EXCH-001 DB_G 82 1,241.31 MB 105.63 GB 0.56 GB 35.35 GB 23.7% 35.35 GB 23.7% Yes (1)
    MAN-EXCH-001 DB_H 82 1,175.95 MB 103.38 GB 1.01 GB 37.91 GB 25.4% 37.91 GB 25.4% Yes (1)
    MAN-EXCH-001 DB_J 82 1,195.55 MB 103.76 GB 1.44 GB 38.38 GB 25.8% 38.38 GB 25.8% Yes (1)
    MAN-EXCH-001 DB_L 82 1,210.02 MB 106.51 GB 2.80 GB 35.94 GB 24.1% 35.94 GB 24.1% Yes (1)
    MAN-EXCH-001 DB_E 83 1,148.04 MB 103.76 GB 0.04 GB 38.18 GB 25.6% 38.18 GB 25.6% Yes (1)
    MAN-EXCH-001 DB_F 83 1,169.19 MB 102.76 GB 0.05 GB 39.63 GB 26.6% 39.63 GB 26.6% Yes (1)
    MAN-EXCH-001 DB_I 82 1,200.10 MB 101.38 GB 0.05 GB 99.76 GB 44.3% 99.76 GB 44.3% Yes (1)
    MAN-EXCH-001 DB_M 17 1,204.85 MB 24.38 GB 0.01 GB 67.12 GB 45.0% 67.12 GB 45.0% Yes (1)

    • Have you tried the solution in a post above using the “sort Name” or “sort-object Name” in the right places in the script?

  7. Dear Steve,

    is it possible to add public folder whitespace from exchange 2003?

    Thanks in advance,
    André

  8. Running version 1.5.4.

    I noticed a small oversight – that when there is only one mailbox in a database (because we’re just setting up coexistence with 2010 and testing) it takes the size of the mailbox and halves it to get the average mailbox size.

  9. Hey Steve,

    a very nice tool but I have to adapt it to our needs.

    I have added two new filter:
    [parameter(Position=5,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Server Domain Filter (eg NL-*)')][string]$Serverdomain=”[fqdn]“,

    [parameter(Position=5,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Server Name Filter (eg NL-*)')][string]$ServerName=”2c”

    and have changed some queries:
    $ExchangeServers = [array](Get-ExchangeServer -Domain $ServerDomain) | where-object {($_.Name -match $ServerName)}

    $Mailboxes = [array](Get-ExchangeServer -Domain $ServerDomain | where-object {($_.Name -match $ServerName)} |Get-Mailbox -ResultSize Unlimited)

    $Databases = [array](Get-ExchangeServer -Domain $ServerDomain | where-object {($_.Name -match $ServerName)} | Get-MailboxDatabase -IncludePreExchange2007 -Status | Sort-Object)

    due to this changes the servers and databases are sorted and you have the amount of MBXs per Store within the report.

  10. Hey paul,

    When i ran the script i got the below error

    [PS] C:\>.\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\rep.html
    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Out-File : Access to the path 'C:\rep.html' is denied.
    At C:\Get-ExchangeEnvironmentReport.ps1:974 char:19
    + $Output | Out-File <<.\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\rep.html
    WARNING: Active Directory server settings remained unchanged.
    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Out-File : Access to the path 'C:\rep.html' is denied.
    At C:\Get-ExchangeEnvironmentReport.ps1:974 char:19
    + $Output | Out-File <<

  11. Hey paul,

    When i ran the script i got the below error

    [PS] C:\>.\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\rep.html
    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Out-File : Access to the path 'C:\rep.html' is denied.
    At C:\Get-ExchangeEnvironmentReport.ps1:974 char:19
    + $Output | Out-File <<<
    [PS] C:\>.\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\rep.html
    WARNING: Active Directory server settings remained unchanged.
    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:472 char:29
    + if ($TotalServersByRole[ <<<< $Role] -eq $null)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:123 char:60
    + $MailboxStatistics = [array]($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].MailboxStatistics | Where
    {$_.Database -eq $Database.Identity})
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Index operation failed; the array index evaluated to null.
    At C:\Get-ExchangeEnvironmentReport.ps1:134 char:35
    + if ($ExchangeEnvironment.Servers[ <<<< $Database.Server.Name].Disks)
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:193 char:140
    + $Size = [long](get-wmiobject cim_datafile -computername $Database.Server.Name -filter ('name=''' + $Database.
    edbfilepath.pathname.replace <<<< ("\","\\") + '''')).filesize
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    WARNING: Cannot detect database size via WMI for
    You cannot call a method on a null-valued expression.
    At C:\Get-ExchangeEnvironmentReport.ps1:213 char:50
    + ActiveOwner = $Database.Server.Name.ToUpper <<<< ()
    + CategoryInfo : InvalidOperation: (ToUpper:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Out-File : Access to the path 'C:\rep.html' is denied.
    At C:\Get-ExchangeEnvironmentReport.ps1:974 char:19
    + $Output | Out-File <<<
    [PS] C:\>

  12. Hi Steve,

    Just wanted to thank you for sharing the script. It’s helped me a great deal. Thank you!

  13. Hey Steve,

    great script! But sometimes the rollup versions is not detected correctly.

    Get-ExchangeUpdateRollups.ps1 gives the correct output.

    http://www.bhargavs.com/index.php/2009/12/14/how-do-i-check-update-rollup-version-on-exchange-20xx-server/

  14. Hi Steve, Thanks for the great script. How do I change the filter to exclude. I got few 2003 FE servers on DMZ which are not accessible and would like to skip instead of timing out.

  15. I have noticed that the logs free space reports incorrect. Every run always shows 96.8% free even when I have verified that on log drive was 40% free. Seems to be only on mount point drives (but the DB are also on MP and they report correctly)

  16. I am getting lots of error while executing the script.
    Unexpected token ‘UR’ in expression or statement.
    At C:\Scripts\Get-ExchangeEnvironmentReport.ps1:537 char:17
    + $Output+=” UR( <<<< $Server.RollupLevel)"

  17. Hi Steve, is it possible to change the sort order inside the HTML report? i have a 2 member DAG in my enviroment and the reports sorts the list by servername. can i change a parameter to sort the list by database name?
    THX
    Jens

  18. Great Script.

    I read the above posts and would like to add. SCOM monitoring is not soo great out of the box when you have such large drives ( for email alerts).
    I tried to modify your script but could not get the database list sorted by name. I would really appreciate. Seems to list databases differently on different runs.
    Mark

    • Use the Sort-Object in BOTH locations in section 2.1:
      {
      _UpProg1 60 “Getting Archive Mailboxes” 1
      $ArchiveMailboxes = [array](Get-Mailbox -Archive -ResultSize Unlimited) | Where {$_.Server -like $ServerFilter}
      _UpProg1 90 “Getting Databases” 1
      $Databases = [array](Get-MailboxDatabase -IncludePreExchange2010 -Status) | Where {$_.Server -like $ServerFilter} |sort-object Name
      $DAGs = [array](Get-DatabaseAvailabilityGroup) | Where {$_.Servers -like $ServerFilter}
      } else {
      $ArchiveMailboxes = $null
      $ArchiveMailboxStats = $null
      $DAGs = $null
      _UpProg1 90 “Getting Databases” 1
      $Databases = [array](Get-MailboxDatabase -IncludePreExchange2007 -Status) | Where {$_.Server -like $ServerFilter} | sort-object Name

    • Ok. I found the spot for gettting the database list (at least for DAG) sorted by name.
      Line 820, I added ” | Sort Name ” To the end.

      $Databases = [array](Get-MailboxDatabase -IncludePreExchange2010 -Status) | Where {$_.Server -like $ServerFilter} | sort Name

      Thanks,
      Mark

  19. would love to have PF data added to this report..

    Thanks!

  20. Great report. i’d love to add in the last Incremental backup date into the report. Other than that, this report ROCKS!!!!

  21. Awesome script!!! Trying to get it to run as a task but it wont. Tried copying the powershell push command to a batch file but still no luck. Windows 2008 R2 here. Any help would be greatly appreciated. Thanks.

    • Figured it out. We have Exchange 2010. Created a batch file with the following command and created a Task scheduler task to run nightly:
      powershell.exe -command “. ‘D:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1′; Connect-ExchangeServer -auto; c:\scripts\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\scripts\ev-report.html -SendMail:$true -MailFrom:cas-hub@nowhere.com -MailTo:me@somewhere.com -MailServer:server.domain.com”

  22. Many environments have Edge servers protected with TMG which blocks WMI and Remote Registry. Rather than having to open up the ports for these services, which is a hard sell for security watchdogs in most environments, it’d be desirable to have another switch in the script to skip the Edge servers.

    Cheers

  23. Steve, thank you for this wonderful script! The report is elegant and well laid out.

  24. Thank you very much Steve
    Hope next version, you can add 04 more things:
    1. Ability to save the file as date format (to keep history)
    2. Show all Servers status not only DAG activated Server (at our side, Servers in DAG are not the same Physical, HDD…)
    3. Add RAM, CPU Status.
    4. Message queue.

    Phong

  25. Great tool! Just wondering if there is anyway to add functionality where when the database disk free size gets to 2% or something like that, can the box turn to RED?

    • Hi Jeremy,

      To be honest functionality like that I would personally think SCOM would be more suitable for as real monitoring systems provide better real-time reporting and more in depth analysis of actual issues. It’s possible to change the script to do this however.

      Steve

  26. Hey Steve,

    this is an awsesome script!
    When running it in an environment with Exchange Edge servers, it stops due to permissions errors (no access to Edge server). It’s a predictable behaviour, since the edge server is not a member of AD. Is there a way to a) identify Edge servers and b) prompt for credentials?

    I can send you the error messages for exploration, if you like.

    Regards,
    Heiko

  27. Dear Steve,

    thank you very much for your excellent script. I have the same problems with the mailbox count. If the script runs to the hole forest it works. If I set up an Filter for example (de*) the mailbox count is always empty.

    Could you help me?

  28. Hi Paul,

    i have also some problems with the mailbox counts. When the script runs without a serverfilter the mailbox count works. If i set a filter for example “de*” the mailbox count is always empty.

    Could you help me please?

  29. Hey Steve

    Awesome script, well written. Wow!!! Works fine for me manually scheduled from a Win2008/Exch2007 HT Server. However, when I use the -ServerFilter, gives me 0 count for mailboxes, both Total and individual DBs. Any idea? Thanks

  30. Steve, running v1.5.4 but not getting any of the Mailboxes counts (total or indivudual db). Everything else displays great.

    Also, along with others is there way to run the script either Domain or Site specific? Each domain\site manages their own Exchange servers within the Enterprise.

    Thanks,
    Jay

    • Ran against Entire forest and mailbbox counts populate for the domain which I manage (do not have rights in the other domains). Running using Server Filter on my domain mailboxes does not produces the mailbox counts.

      Is there a way to accomplish this? Would be nice to run against just those servers during user migration from 2007 to 2010.

      Thanks,
      Jay

  31. Hi,

    I think you made a little mistake in log free space % evaluation

    This line:
    if ( $Database.LogFolderPath.PathName -like “$($Disk.Name)*”)
    To:
    if ( ($($Database.LogFolderPath.PathName+”\”)) -like “$($Disk.Name)*”)

    In my case, with a mount point for the log, LogFolderPath.PathName end with no “\”, and disk name has one ! So the -like did not match.

    If not clear, give it a try it if you have problem with free log space :-)

    Best regards.

  32. GREAT SCRIPT

    Script runs fine by command line, but when I add to the task in Windows 2008, it never runs. (running as same account that i used manually) – no said errors other then the 0×1
    I did try a few things to test copy past the lines from task manager and run from command line. i do get an error when i do that..
    here is the command that i have copied and pasted.

    -c “pushd C:\Exchange\Scripts; C:\Exchange\Scripts\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\ExchangeReports\ExchangeReport.html -SendMail:$true -MailFrom:ExchangeReport@fake.com -MailTo:fakeDL@fake.com -MailServer:someserver

    Error:

    Push-Location : A parameter cannot be found that matches parameter name ‘HTMLRe
    port’.
    At line:1 char:72
    + pushd C:\Exchange\Scripts\Get-ExchangeEnvironmentReport.ps1 -HTMLReport <<<<
    c:\ExchangeReports\ExchangeReport.html -SendMail:$true -MailFrom:ExchangeRepor
    t@fake.com -MailTo:fake@fake.com -MailServer:someserver
    + CategoryInfo : InvalidArgument: (:) [Push-Location], ParameterB
    indingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm
    ands.PushLocationCommand

    can you point me in the right direction?

    • any thoughts on the above error or any suggestions on getting this as a task?

    • Here is what I used in a batch file and scheduled in Task Scheduler: powershell.exe -command “. ‘D:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1′; Connect-ExchangeServer -auto; c:\scripts\Get-ExchangeEnvironmentReport.ps1 -HTMLReport c:\scripts\ev-report.html -SendMail:$true -MailFrom:cas-hub@nowhere.com -MailTo:me@somewhere.com -MailServer:server.domain.com”

      • yep i finally did that as well
        called a bat file from sched task
        bat file reads:
        powershell -command “& c:\scripts\Get-ExchangeEnvironmentReport.ps1 -HTMLReport ExchangeReport.html -SendMail:$true -MailFrom:some@address.com -MailTo:another@address.com -MailServer:smtpserver”

  33. Steve…

    I try to set up the script as a task per instructions above, and keep getting this:
    + CategoryInfo : InvalidArgument: (:) [Get-ExchangeEnvironmentReport.ps1], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousPositionalParameterNoName,Get-ExchangeEnvironmentReport.ps1

    What am I doing wrong?

  34. What a nice script/report! Thank you, Steve. One request… It would be nice if the report showed the Exchange edition (Ent or Std), like it does for the OS.

  35. Thanks billion Steve.
    PERFECT script, looking forward to your solutions to my issues explained in my email.

  36. Hi , when i try to run the Script, i receive the following error.

    Incomplete ‘finally’ statement. A finally statement requires a body.
    At C:\Documents and Settings\aroura\Desktop\Get-ExchangeEnvironmentReport.ps1:4
    4 char:9
    + Finally, <<<< per Database (Non DAG DBs/Exchange 2007/Exchange 2003)

    Any idea?

    Thank you.

  37. Great script Steve,

    Worked a treat for me. I thought i was doing well with powershell until a read through the script.
    In the first function _GetDAG…i can see you define your param and create an array and an empty array….how did you get the database info. There is no get-mailboxdatabase command…….what dark magic is this?

    Thanks
    Emmet

  38. Great script! Definitely saved me a lot of work. Thanks!!

  39. Great script Steve,

    I thought i was doing ok with powershell until i read your script.
    Could you explain how the first function works (Function _GetDAG) ?
    How do you get the database info with so few lines of code. You dont use get-mailboxdatabase?? Probably a dumb question…but i’m scratching my head here.

    Cheers
    Emmet

  40. Steve, great script! Having an issue with the “DB whitespace” calculation. The “DB whitespace” calc comes out as the same as the “DB Size” on 2K3 servers and on 2K7 SP2 CCR it comes out as a very high value as compared to what results from running 2 other scripts that report the same value. (example: your script reports DB1 having a DB size of 101.92 GB and DB Whitespace of 46.50 GB. I run 2 differnet scripts to check for whitespace only and they both come up with 2.55 GB for DB1 whitespace).

    Could you explain how your script calculates DB whitespace?

  41. Hi Steve,

    looks like I found little room for improvement (to avoid the b-word) in your marvellous tool :)
    The “Av. Mailbox Size” for Exchange 2003 databases is calculated wrong somehow (for all 2k3 DBs).
    Sample: 248 Mailboxes, 38.43GB DB Size (and almost 0 whitespace) -> Av MBX Size = 0.10MB.
    Version is v1.5.4.

    Best wishes,
    Klaus

  42. Hi Steve,

    I am little bit confused about this script, kindly assist me , how to use this script..

    Thanks

  43. Great thing by the way. to things for your whish list :-)
    1. “free Disk space” is not correct if we are using MountPoint
    2. add the “path” to the Database/logs as an additional column

    Frank

  44. If -SendMail specified, you must also specify -MailFrom, -MailTo and -MailServer ???

    But I am putting those in…

  45. Hi Steve,

    I got a question,

    When I´m running the script I get a “Security Warning”

    .\Get-ExchangeEnvironmentReport -HTMLReport C:\Scripts\ExchangeEnvironmentReport.html

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

    To run the script I need to confirm with “R” key, the problem is when I add the script to schedule task, the script don’t run because of this, is there anything I can add to the command line to supersede the “R” key.

    ExecutionPolicy is set to “Unrestricted”

    • Hi Adam,

      A quick woraround may be to crate a new Powershell file and copy/paste the script from the original file into the new file, to ensure it’s seen as a local file.

      Steve

    • You can also open Explorer, right click on the file, select Properties. You should have an option at the bottom of the General tab to Unblock the script.

  46. Hi Steve,

    not sure how can we twick in your script only scan per-sites or server only ?

  47. The Script is very Good , Is there is any possibility of splitting these scripts Individually ?
    and also is there is anyway to run these scripts across domain wisw and Server Wise , In our Exchange Environment we do not have access to all the domains and Servers, It will be good f you could guide me on Server Wise.

    Regards
    Srinivasa K

  48. Hello Steve

    The Script is very good , Is there is any posibilities of running this script individually and specific to Domain Wise. We have multiple Doamins in our forest and we have access only to few Domains and Servers.

    I want to split these scrips Individually . Please help Me.

  49. Steve,

    I was in the process of writing a powershell script that does all of this… man, you saved me a bunch of work! Thanks so much. This is great. You did a fantastic job with the format of the report as well!

    Do you have any plans to do something similar with Lync? I’m going to start one. I’m sure it won’t be nearly as pretty as anything you’d write. Thanks and Cheers!


Leave a comment

(required)