MailboxDistribution.psm1

#region Get-MailboxesPerServer
Function Get-MailboxesPerServer
{
    <#
    .SYNOPSIS
 
    Get the number of mailboxes per server.
    .DESCRIPTION
 
    The Get-MailboxesPerServer cmdlet returns the total number of mailboxes per server.
    .PARAMETER Server
 
    The name of the exchange server.
    .EXAMPLE
    Get-MailboxesPerServer -Server Exchange2013
 
    This command will return the number of mailboxes on server Exchange2013
 
    .EXAMPLE
    Get-MailboxServer | Get-MailboxesPerServer
 
    This command will return the number of mailboxes on all mailbox servers, per server.
    #>


    [cmdletBinding()]

    Param
    (
        [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Name')]
        [string[]]$Server = $env:COMPUTERNAME,

        # Include AutoSuspended mailboxes
        [Parameter(Mandatory = $false, Position = 1)]
        [switch]$IncludeAutoSuspended
    )

    Begin
    {
        try
        {
            Get-Command "Get-Mailbox" -ErrorAction Stop |
                Out-Null
        }
        catch
        {
            Throw "Could not find the Exchange cmdlets."
        }

        #region Get the move requests
        if($IncludeAutoSuspended)
        {
            Write-Verbose "Getting AutoSuspended move requests."
            $moveRequests = Get-MoveRequest -MoveStatus "AutoSuspended" -ResultSize Unlimited
        }
        #endregion

    }

    Process
    {
        # Loop through the servers
        foreach($s in $Server)
        {
            # Get the databases
            Write-Verbose ("Getting databases of server " + $s)
            $databases = Get-MailboxDatabaseCopyStatus -Server $s | Where-Object {$_.Status -eq "Mounted"}

            # Get the mailboxes on throse databases
            Write-Verbose ("Getting mailboxes of databases")
            $mailboxes = @()
            $autosuspended = 0
            foreach($d in $databases)
            {
                Write-Verbose ("`tGetting mailboxes of database " + $d.DatabaseName)
                $mailboxes += Get-Mailbox -Database $d.DatabaseName

                if($IncludeAutoSuspended)
                {
                    $autosuspended += @($moveRequests | Where-Object {$_.TargetDatabase -eq $d.DatabaseName}).Count
                }
            }

            # Create a custom object
            $obj = New-Object PSObject -Property @{
                                                    "Server" = $s
                                                    "Mailboxes" = $mailboxes.Count
                                                 }

            #region Get the autosuspended mailboxes of the server
            if($IncludeAutoSuspended)
            {
                Write-Verbose "Getting AutoSuspended mailboxes of $s"
                if($autosuspended -eq $null)
                {
                    $autosuspended = 0
                }
                $obj | Add-Member NoteProperty "AutoSuspendedMailboxes" $autosuspended
            }
            #endregion
            $obj
        }
    }

    End {}
}
#endregion

#region Get-MailboxesPerDatabase
Function Get-MailboxesPerDatabase
{
    <#
    .SYNOPSIS
 
    Get the number of mailboxes per database.
    .DESCRIPTION
 
    The Get-MailboxesPerDatabase cmdlet returns the total number of mailboxes per database on an exchange server.
    .PARAMETER Server
 
    The name of the exchange server.
    .EXAMPLE
    Get-MailboxesPerDatabase -Server Exchange2013
 
    This command will return the number of mailboxes per database on server Exchange2013
 
    .EXAMPLE
    Get-MailboxServer | Get-MailboxesPerDatabase
 
    This command will return the number of mailboxes per database on all mailbox servers.
    #>


    [cmdletBinding()]

    Param
    (
        [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]]$Server = $env:COMPUTERNAME,

        # Include AutoSuspended mailboxes
        [Parameter(Mandatory = $false, Position = 1)]
        [switch]$IncludeAutoSuspended
    )

    Begin
    {
        try
        {
            Get-Command "Get-Mailbox" -ErrorAction Stop |
                Out-Null
        }
        catch
        {
            Throw "Could not find the Exchange cmdlets."
        }    

        #region Get the move requests
        if($IncludeAutoSuspended)
        {
            Write-Verbose "Getting AutoSuspended move requests."
            $moveRequests = Get-MoveRequest -MoveStatus "AutoSuspended" -ResultSize Unlimited
        }
        #endregion
    }

    Process
    {
        # Loop through the servers
        foreach($s in $Server)
        {
            # Get the databases
            Write-Verbose ("Getting databases of server " + $s)
            $databases = Get-MailboxDatabaseCopyStatus -Server $s | Where-Object {$_.Status -eq "Mounted"}

            # Loop through databases
            Write-Verbose ("Getting mailboxes of databases")
            foreach($d in $databases)
            {
                # Get the mailboxes
                Write-Verbose ("`tGetting mailboxes of database " + $d.DatabaseName)
                $mailboxes = @(Get-Mailbox -Database $d.DatabaseName)

                # The autosuspended mailboxes
                $autosuspended = 0

                # Create a custom object
                $obj = New-Object PSObject
                $obj | Add-Member NoteProperty "Server" $s
                $obj | Add-Member NoteProperty "Database" $d.databasename
                $obj | Add-Member NoteProperty "Mailboxes" $mailboxes.Count


                if($IncludeAutoSuspended)
                {
                    $autosuspended = @($moveRequests | Where-Object {$_.TargetDatabase -eq $d.DatabaseName}).Count
                    if($autosuspended -eq $null)
                    {
                        $autosuspended = 0
                    }
                    $obj | Add-Member NoteProperty "AutoSuspendedMailboxes" $autosuspended
                }

                $obj
            }
        }
    }

    End {}
}
#endregion

#region Get-MilboxesPerDatabaseAvailabilityGroup
Function Get-MailboxesPerDatabaseAvailabilityGroup
{
    <#
    .Synopsis
       Get the mailbox distribution on DAGs
    .DESCRIPTION
       Get the mailbox distribution on Database Availability Groups, optionaly including AutoSuspended mailboxes.
    .EXAMPLE
        [PS] C:\>Get-MailboxesPerDatabaseAvailabilityGroup -DatabaseAvailabilityGroup DAG1
 
        DAG Servers Databases Mailboxes
        --- ------- --------- ---------
        DAG1 8 18 851
 
        Get the mailboxes on DAG1.
     
    .EXAMPLE
        [PS] C:\>Get-DatabaseAvailabilityGroup | Get-MailboxesPerDatabaseAvailabilityGroup
        DAG Servers Databases Mailboxes
        --- ------- --------- ---------
        DAG1 8 18 851
        DAG2 4 9 259
         
        Get the mailboxes on all Database Availability Groups
 
    .EXAMPLE
        [PS] C:\>Get-DatabaseAvailabilityGroup DAG1 | Get-MailboxesPerDatabaseAvailabilityGroup -IncludeAutoSuspended | Format-Table
 
        DAG Servers Databases Mailboxes AutoSuspendedMailboxes
        --- ------- --------- --------- ----------------------
        DAG1 8 18 851 34
 
        Get the mailboxes on DAG1 including the AutoSuspended.
    .NOTES
       The AutoSuspended mailboxes are not included in the database mailboxes.
    #>


    [cmdletBinding()]

    Param
    (
        # The DAG to query
        [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Name')]
        [string[]]$DatabaseAvailabilityGroup,

        # Include AutoSuspended mailboxes
        [Parameter(Mandatory = $false, Position = 1)]
        [switch]$IncludeAutoSuspended        
    )

    Begin
    {
        #region Environment Check
        # Check if Exchange cmdlets are available
        Write-Verbose "Checking for Exchange cmdlets."
        try
        {
            Get-Command "Get-DatabaseAvailabilityGroup" -ErrorAction Stop |
                Out-Null
        }
        catch
        {
            Throw "Could not find Exchange cmdlets."
        }
        #endregion

        #region Get the move requests
        if($IncludeAutoSuspended)
        {
            Write-Verbose "Getting AutoSuspended move requests."
            $moveRequests = Get-MoveRequest -MoveStatus "AutoSuspended" -ResultSize Unlimited
        }
        #endregion
    }

    Process
    {
        #region Get Database Availability Groups
        if($DatabaseAvailabilityGroup)
        {
            $dags = @()
            foreach($dagp in $DatabaseAvailabilityGroup)
            {
                try
                {
                    Write-Verbose "Getting Database Availability Group $dagp."
                    $dags += Get-DatabaseAvailabilityGroup $dagp -ErrorAction Stop
                }
                catch
                {
                    Write-Error "Could not find a Database Availability Group for $dagp"
                }
            }
        }
        else
        {
            Write-Verbose "Getting Database Availability Groups."
            $dags = Get-DatabaseAvailabilityGroup
        }
        #endregion

        #region Process Each DAG
        foreach($d in $dags)
        {
            Write-Verbose "`tProcessing DAG $($d.Name)"

            #region Create a custom object per DAG
            $obj = New-Object psObject
            $obj | Add-Member NoteProperty "DAG" $d.Name
            #endregion

            #region Get the servers of the DAG
            Write-Verbose "`tGetting servers of $($d.Name)"
            # Exchange Shell and Implicit Remoting return different objects
            # and we need to check both
            $srvs = $d.Servers
            if($srvs.Name -ne $null)
            {
                $servers = $srvs.Name
            }
            else
            {
                $servers = $srvs
            }
            $obj | Add-Member NoteProperty "Servers" $servers.Count
            #endregion

            #region Get the databases on these servers
            Write-Verbose "`tGetting databases of $($d.Name)"
            $databases = $servers | %{ Get-MailboxDatabaseCopyStatus -Server $_ | Where-Object {$_.Status -eq "Mounted"} } | % DatabaseName
            $obj | Add-Member NoteProperty "Databases" $databases.count
            #endregion

            #region Get the mailboxes of the database
            Write-Verbose "`tGetting mailboxes of $($d.Name)"
            $mailboxes = $databases | %{ Get-mailbox -Database $_ -ResultSize unlimited}
            $obj | Add-Member NoteProperty "Mailboxes" $mailboxes.count
            #endregion

            #region Get the autosuspended mailboxes of the dag
            if($IncludeAutoSuspended)
            {
                Write-Verbose "Getting AutoSuspended mailboxes of $($d.Name)"
                $autosuspended = $moveRequests | Where-Object {$_.TargetDatabase -in $databases}
                $obj | Add-Member NoteProperty "AutoSuspendedMailboxes" $autosuspended.Count
            }
            #endregion

            # Send the custom object to the pipeline
            $obj
        }
        #endregion
    }

    End{}
}
#endregion

#region Exports
Export-ModuleMember -Function Get-MailboxesPerDatabase
Export-ModuleMember -Function Get-MailboxesPerServer
Export-ModuleMember -Function Get-MailboxesPerDatabaseAvailabilityGroup
#endregion