Finding disconnected mailboxes the PowerShell and EMS way

Like most IT books, Microsoft Exchange Server 2010 Inside Out is a huge doorstop of a book. Since my boss was kind enough to purchase it, and I’m by far the department’s foremost reader of English and its least-experienced Exchange admin, I’ve decided to try to read the whole thing, a chapter a day.

It’s already paid off – I solved a problem using it just a day after reading the fantastic “Exchange Management Shell” chapter.

When a user gets transferred to a location in another domain in our Active Directory forest, he gets a new user account in that domain, but his old mailbox is moved to the Exchange server for that location in the new domain. Occasionally, something goes wrong and the mailbox ends up in a disconnected state – in this case, the old account was deleted before the mailbox was connected to the new one. The real problem was that the help desk staff member who did the move couldn’t remember which mailbox database (or even server) he moved the mailbox to…

Exchange Management Shell and Tony Redmond to the rescue!

The script below is adapted from “Exchange Server 2010 Inside Out”, page 132, mostly to overcome the pipelining problem Tony describes in the “Code changes required by remote PowerShell” section on page 120. I ran this, as I run everything I can, in an implicit Exchange remoting session in my trusty PowerGUI, rather than in Exchange Management Shell itself. Make sure you are either implicitly remoted to an Exchange server or in Exchange Management Shell before running it.

$mbxServers = (Get-MailboxServer | ForEach-Object { $_.name })
Foreach ($mbxserver in $mbxServers) {Get-MailboxStatistics -Server $mbxserver `
| where {$_.disconnectdate -ne $null } | select displayname,OriginatingServer, `
DisconnectDate,LastLoggedOnUserAccount,LastLogonTime,TotalItemSize,Database `
| Export-Csv c:\temp\$mbxserver-disconnectedmailboxes.csv -NoTypeInformation }

The main weakness is that it will only find disconnected mailboxes on 2007 or 2010 servers, but that’s because Get-MailboxStatistics only works on those newer mailboxes.

Tony Redmond’s blog: http://thoughtsofanidlemind.wordpress.com/

Getting ints out of Exchange 2010 disk space statistics Strings when remoting

July 2015 update: This still applies to Exchange 2013 – I’ve not tested it yet with Exchange 2016, though…

I’m back, this time with Exchange stuff. It’s been awhile, mostly due to my company’s IT department having found out what happens when DNS and AD do not get along and everything starts falling back to NTLM authentication, as well as a long Thanksgiving vacation back to the States. However, I’ve begun a project to overhaul our old user provisioning process, and ActiveRoles Server is at the center of it.

User provisioning means email provisioning, and in an Exchange environment, that means Exchange cmdlets.

The PowerShell cmdlets for Exchange 2010 are about 90% awesome. Why not 100%? Little stuff like returning disk space statistics from Get-MailboxDatabase -Status or Get-MailboxStatistics as strings when doing implicit remoting, not the ByteQuantifiedSize type returned when you use Exchange Management Shell on the server itself, or as a simple int.

This is because ByteQuantifiedSize is not a regular .NET type, but a Microsoft.Exchange.Data type, so instead of rendering it as a plain-vanilla int when the Microsoft.Exchange.Management.PowerShell.E2010 snap-in isn’t loaded, PowerShell renders it as a String. Microsoft wants us to use implicit remoting instead of the snap-in when running remotely. Make up your minds, Exchange team!

Technet forum discussion about this inconsistency: Exchange Server 2010: why string here and int there with EMC?

Example:

Get-MailboxDatabase -Server US1234 -Status `
| Select-Object AvailableNewMailboxSpace `
| Sort-Object -Descending


AvailableNewMailboxSpace
------------------------
94.88 MB (99,483,648 bytes)
1.58 GB (1,696,464,896 bytes)

Wait… 1.58 GB is bigger than 94.88 MB, right? Not if they’re strings.

However, this can be overcome. I’m posting this because all the ways I could find are stuck deep inside rather long scripts. This method is from http://poshcode.org/1902, by Karl Mitschke (see line 120). I chose to leave it as bytes rather than converting to MB or GB, as the destination for this data is a SQL Server table that will immediately be used for the user provisioning project, but might be used for other things in the future.

Our mailbox databases are named for the sites they’re at: for example, one of the ones at the US-Dallas site would be US-Dallas-MD01. The sitename can be extracted with Split(‘-‘).

Get-MailboxDatabase -Status `
| Select-Object @{Name="Sitename"; `
Expression={$_.Name.split('-')[0]+'-'+$_.Name.split('-')[1]}}, `
Name, Server, `
@{Name="Available"; `
Expression={[int]($_.availablenewmailboxspace.split("(")[1].Split()[0])}} `
| Sort-Object -Property @{Expression="Sitename";Descending=$false}, `
@{Expression="Available";Descending=$true}

That finally got me what I was looking for.

Here’s a function for converting those disk space strings to integers – I’ve added it to the script I use to start Exchange implicit remoting sessions from my workstation.

Function Get-IntFromExchangeNumberString {
Param($NumberString)
 [int]($NumberString.split("(")[1].Split()[0])
}

If there is a better and/or more concise way to do any of what I’ve done, feel free to put it in the comments or post a link!