I often receive questions from people who are looking at some PowerShell examples here on Exchange Server Pro but want to know how to combine the output from different examples into a single script or report.

This is something I do in almost all of the PowerShell scripts I’ve published here, and you’re free to look at the code in them and use it elsewhere or customize it for your own needs. But I also wanted to give you a simple demonstration of the technique here.

Let’s say you want to write a script that will tell you the name, department, database name, and mailbox storage quota info for a mailbox.

Those are all pieces of information we can get from different PowerShell cmdlets:

  • Name can come from Get-Mailbox, Get-Recipient, or Get-MailboxStatistics (and others for that matter)
  • Department can come from Get-Recipient
  • Database name can come from Get-Mailbox or Get-MailboxStatistics
  • Get-Mailbox will also tell us if the mailbox is configured to use the database default quota values
  • The storage limit status (above or below quota limit) comes from Get-MailboxStatistics
  • The quota levels themselves can come from Get-Mailbox or Get-MailboxDatabase, depending on whether the mailbox is using database quota defaults or not

So as you can see the data we’re interested in can come from multiple cmdlets.

So now let’s build a simple script that fetches the data using those multiple PowerShell cmdlets, and then uses a PowerShell custom object to combine it all for output.

First, let’s fetch the data (my script has a parameter -Mailbox, hence the $mailbox in the example here).

#Fetch the various bits of data we're interested in
$mbx = Get-Mailbox $Mailbox
$recipient = Get-Recipient $mailbox
$mbxstats = Get-MailboxStatistics $mailbox
$database = Get-MailboxDatabase $mbx.Database

Next, we can create a custom object. Where I’m using $MailboxObject you can really use anything you like. I often simply use $ReportObj.

#Create the custom object
$MailboxObject = New-Object PSObject

Now let’s start adding properties and values to the custom object.

#Begin adding the values to the custom object properties

$MailboxObject | Add-Member NoteProperty -Name "Name" -Value $mbx.Name
$MailboxObject | Add-Member NoteProperty -Name "Department" -Value $recipient.Department
$MailboxObject | Add-Member NoteProperty -Name "Storage Limit Status" -Value $mbxstats.StorageLimitStatus
$MailboxObject | Add-Member NoteProperty -Name "Database" -Value $mbx.Database
$MailboxObject | Add-Member NoteProperty -Name "Uses Database Quota Defaults" -Value $mbx.UseDatabaseQuotaDefaults

As you can see it is as simple as giving each property a unique name, such as “Department”, and then assigning the value for that property such as $recipient.Department (remember that $recipient is what I fetched earlier with Get-Recipient).

You don’t need to match the property names and values precisely. I could just as easily use this instead:

$MailboxObject | Add-Member NoteProperty -Name "Dept" -Value $recipient.Department

But obviously for neatness and readability it pays to use property names that make sense.

Now comes the only “tricky” part of this script. If the mailbox is configured to use the database quota defaults, then we want to grab those values from the database. However if the mailbox is not using the default quota values, then we want to grab those values from the mailbox.

#If the mailbox is configured to use the database quota defaults, we collect those values from the database
if ($($mbx.UseDatabaseQuotaDefaults) -eq $true)
{
    $MailboxObject | Add-Member NoteProperty -Name "Warning Quota" -Value $database.IssueWarningQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Quota" -Value $database.ProhibitSendQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Receive Quota" -Value $database.ProhibitSendReceiveQuota
}
#Otherwise, we want the quota values from the mailbox itself
else
{
    $MailboxObject | Add-Member NoteProperty -Name "Warning Quota" -Value $mbx.IssueWarningQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Quota" -Value $mbx.ProhibitSendQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Receive Quota" -Value $mbx.ProhibitSendReceiveQuota
}

Finally, output the custom object.

#Output the results
$MailboxObject

Here is the complete script code, including the -Mailbox parameter that is used when running the script.

#
# Check-QuotaStatus.ps1
#

#requires -version 2

[CmdletBinding()]
param (
	[Parameter( Mandatory=$true)]
	[string]$Mailbox
	)


#Fetch the various bits of data we're interested in
$mbx = Get-Mailbox $Mailbox
$recipient = Get-Recipient $mailbox
$mbxstats = Get-MailboxStatistics $mailbox
$database = Get-MailboxDatabase $mbx.Database


#Create the custom object
$MailboxObject = New-Object PSObject


#Begin adding the values to the custom object properties

$MailboxObject | Add-Member NoteProperty -Name "Name" -Value $mbx.Name
$MailboxObject | Add-Member NoteProperty -Name "Department" -Value $recipient.Department
$MailboxObject | Add-Member NoteProperty -Name "Storage Limit Status" -Value $mbxstats.StorageLimitStatus
$MailboxObject | Add-Member NoteProperty -Name "Database" -Value $mbx.Database
$MailboxObject | Add-Member NoteProperty -Name "Uses Database Quota Defaults" -Value $mbx.UseDatabaseQuotaDefaults

#If the mailbox is configured to use the database quota defaults, we collect those values from the database
if ($($mbx.UseDatabaseQuotaDefaults) -eq $true)
{
    $MailboxObject | Add-Member NoteProperty -Name "Warning Quota" -Value $database.IssueWarningQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Quota" -Value $database.ProhibitSendQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Receive Quota" -Value $database.ProhibitSendReceiveQuota
}
#Otherwise, we want the quota values from the mailbox itself
else
{
    $MailboxObject | Add-Member NoteProperty -Name "Warning Quota" -Value $mbx.IssueWarningQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Quota" -Value $mbx.ProhibitSendQuota
    $MailboxObject | Add-Member NoteProperty -Name "Send Receive Quota" -Value $mbx.ProhibitSendReceiveQuota
}


#Output the results
$MailboxObject

Now let’s see the result when we run the script against some mailboxes.

[PS] C:Scripts>.Check-QuotaStatus.ps1 -Mailbox alan.reid

Name                         : Alan.Reid
Department                   : Finance Office
Storage Limit Status         : BelowLimit
Database                     : MB-HO-04
Uses Database Quota Defaults : True
Warning Quota                : 18.99 GB (20,394,803,200 bytes)
Send Quota                   : 20 GB (21,474,836,480 bytes)
Send Receive Quota           : 23 GB (24,693,964,800 bytes)


[PS] C:Scripts>.Check-QuotaStatus.ps1 -Mailbox alex.heyne

Name                         : Alex.Heyne
Department                   :
Storage Limit Status         : BelowLimit
Database                     : MB-BR-01
Uses Database Quota Defaults : False
Warning Quota                : 7.813 GB (8,388,608,000 bytes)
Send Quota                   : 8.789 GB (9,437,184,000 bytes)
Send Receive Quota           : unlimited

I hope that helps you understand how you can use PowerShell custom objects in your scripting tasks. If you have any questions or would like to see this concept covered in more depth please feel free to leave a comment below.

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. Paul

    How would you run this against all your mailboxes?

  2. John Tsang

    Hi Paul,

    Many thanks for this, been trying to get an output that will show all shared mailboxes that haven’t been used for 30 days and longer. What would be the script for that?

    Thanks,
    John

  3. John Mohler

    This is exactly what I have been trying to find. Thanks for that. I do have one question for you. We have a bunch of test mailboxes that have not been logged into yet. Therefore, they do not return any data when we run get-mailboxstatistics. Do you know of an easy way to hit all these mailboxes so that we can export a complete list of our mailboxes that also include totalitemsize?

    1. John Mohler

      Something that would update the last logged in flag?

      1. Avatar photo

        Send them an email. You could do it manually from Outlook, or run a Send-MailMessage command in PowerShell, or even set up an automated welcome email for your entire organization so new user mailboxes get at least one mail item after they’re created.

        https://www.ucunleashed.com/175

  4. China

    Hi Paul, this script is great. Can you tell me how I would run this script against specific mailbox servers to get results on all mailbox recipients in a specific domain?

    Thanks,
    China

    1. Avatar photo

      This is just a conceptual demo. But it comes from a more featured script that I’ve published, Get-MailboxReport.ps1

      https://www.practical365.com/powershell-script-create-mailbox-size-report-exchange-server-2010/

      Note that running against a “server” doesn’t work the same as it used to in 2007 and prior, because mailboxes are homed to databases, not servers (even in a single server deployment).

      But, you can simply run the script for your entire org and filter the CSV file in Excel to get the subset of users that you’re interested in.

      1. China

        Paul, thank you for your valuable contributions to the Exchange world and for your swift reply!

  5. Chamara

    Hi Paul,
    I tested this scrip, but it does not show “Storage Limit Status”. Found the below article about the problem.

    It seems by design on of exchange 2013.

    http://support.microsoft.com/kb/2819389

    Is there any other command we can use to get “StorageLimitStatus” ?

    Cheers,
    Chamara

  6. Chris Brown

    Hi Paul, great article. You can do properties on custom objects easily using hashtables:

    New-Object -Type PSObject -Properties @{
    “Send Quota” = $database.ProhibitSendQuota;
    “Warning Quota” = $database.IssueWarningQuota
    }

    etc.

    This can save a lot of typing and looks (in my opinion) a fair bit better.

Leave a Reply