Wednesday, March 10, 2010

Mailbox Size Gui - Exchange 2010 Remote Powershell version

One of the most popular scripts I've posted over the past few years has been the mailbox size gui for Exchange 2007 which evolved over a few different versions. While this is really only scratching the surface of the kind of cool things you can do with this information time and life hasn't really allowed me to make it better. But what i have managed to do is to port it to work with Exchange 2010 using remote powershell from a Windows 7 workstation.

A few challenges that needed to be solved to do this was first a front-end winform that allowed you to select the Exchange server you want to remote the powershell session to. Then some simple code to establish the remote PS Session which look like this

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")

$form1 = new-object System.Windows.Forms.form
$form1.Text = "Exchange 2010 Remote PS Select"
$form1.size = new-object System.Drawing.Size(400,200)
$ServerName = ""
$conuri = ""
# Add Server DropLable
$snServerNamelableBox1 = new-object System.Windows.Forms.Label
$snServerNamelableBox1.Location = new-object System.Drawing.Size(10,20)
$snServerNamelableBox1.size = new-object System.Drawing.Size(120,20)
$snServerNamelableBox1.Text = "Remote ServerName"
$form1.Controls.Add($snServerNamelableBox1)

$exButton4 = new-object System.Windows.Forms.Button
$exButton4.Location = new-object System.Drawing.Size(10,80)
$exButton4.Size = new-object System.Drawing.Size(125,20)
$exButton4.Text = "Connect"
$exButton4.Add_Click({
$conuri = "http://" + $ServerName + "/PowerShell/"
$form1.close()
})
$form1.Controls.Add($exButton4)


# Add Server Drop Down
$snServerNameDrop1 = new-object System.Windows.Forms.ComboBox
$snServerNameDrop1.Location = new-object System.Drawing.Size(150,20)
$snServerNameDrop1.Size = new-object System.Drawing.Size(160,30)
$snServerNameDrop1.Add_SelectedValueChanged({$ServerName = $snServerNameDrop1.SelectedItem.ToString()})

$form1.Controls.Add($snServerNameDrop1)

$root = [ADSI]'LDAP://RootDSE'
$cfConfigRootpath = "LDAP://" + $root.ConfigurationNamingContext.tostring()
$configRoot = [ADSI]$cfConfigRootpath
$searcher = new-object System.DirectoryServices.DirectorySearcher($configRoot)
$searcher.Filter = '(objectCategory=msExchExchangeServer)'
[VOID]$searcher.PropertiesToLoad.Add("cn")
$searchres = $searcher.FindAll()
foreach ($res in $searchres){
$srvOjb = $res.Properties
$snServerNameDrop1.Items.Add($srvOjb.cn[0])
}

$form1.autoscroll = $true
$form1.Add_Shown({$form1.Activate()})
$form1.ShowDialog()

The next challenge was to do with the way the objects are sent and recieved between remote ps session which is explained in detail here. What this menas is that the Byte Quantified Size type isn't availble so what you recieve at the remote end is the string format version of the data structure which needs a simple parse to retrieve the byte information. With this

function CovertBitValue($String){
$numItempattern = '(?=\().*(?=bytes)'
$matchedItemsNumber = [regex]::matches($String, $numItempattern)
$Mb = [INT64]$matchedItemsNumber[0].Value.Replace("(","").Replace(",","")
return [math]::round($Mb/1048576,0)
}

This still needs a little more testing but seems to work okay I've put a download of the new script here.

33 comments:

Anonymous said...

isn't there anything you can do using the new gridview from PS2 ?
looking into this new control when writing simple enumeration scripts it already gave me some ideas

Glen said...

No that cmdlet is to simplified it provides a level of dumbed down abstraction.

Cheers
Glen

Mital Shah said...

Excellent tool, very useful. Thanks a lot.

Anonymous said...

Great coding

Would like to request the following:

1) We have 3 DB in our environment. Each DB is based on the Quota assigned. DB1 say has superuser with 2GB, DB2 has 600MB for std user. etc... Would like to select to view only the data in each database one at a time instead of all 3 DB's at once.

2) Like to see the quota is based on the quota assigned to that DB in a percentage. So if user is DB1 with a quota of 1GB and they are using 900MB then used quota would be 90%.

Thanks,

Tim said...

This is a great tool but I'm having a problem with it when it comes to running history reports with servers that have a dash (-) in their name (ie. Mail-01). It comes from ShowGrowth function where you're using dashes to split the name and date from the historical files. I fixed it in my copy by using a different delimiter. I'd be happy to send it to you if it would help.

Otherwise this tool is very useful!!

Tim said...

For those that need to get the history portion fixed with server names containing dashes make the following changes.

Update line 310 with the new delimiter (I used an underscore)

$nmArray = $_.name.split("_")


The following lines have been truncated to save space.

Change the Import-Csv's to include the new delimiter (again I used an underscore) on lines 337, 340, 343, 346 so they look something like this (command truncated):

Import-Csv ("$script:HistoryDir\" + $oneday + "_" + ....

Change the $fname value to include the new delimiter in lines 207 & 255 so it looks something like this (command truncated):

$fname = $fname + $datetime.ToString("yyyyMMdd") + "_" ...

I might be missing something somewhere but changing these lines got it to work for me with my server names that include dashes. I considered using something like a tilde (~) or exclamation point (!) as a delimiter but this currently works for me so I'm going to leave it as is.

Good luck!
-Tim

Nizam said...

Excellent work. But it would be great if you can add a scroll box to select a database from a list of available mailbox databases.
Thanks.

jfsullivan said...

nice gui but doesnt work. after i select the mail server it just hangs.

Anonymous said...

Exchange 2010 sp1 quota error script.

Sahin said...

Hello, great script, not only does it do what you say, but it also tells you if there are corrupt mailboxes out there, which was usefull duing our migration.

One question I had was if we wanted to add a column, like the DB that the mailbox is on, or any other column, how whould we add this to your wonderfull script. Thanks!

Anonymous said...

I cannot download the script, please see if it can be made available.

Anonymous said...

never mind download worked fine

Val said...

Great script! Works with a lot of errors in background powershell window, but works :) Thanks a lot! Please update ;)

Chris O. said...

Excellent Tool!
I was amazed after the upgrade from 2003 to 2010 that it did not have this functionality.

bttr said...

This script only partially works on a German Windows SBS 2011:
Ausnahme beim Aufrufen von "Add" mit 1 Argument(en): "Die Eingabezeichenfolge hat das falsche Format.<11.700> konnte n
icht in der Quota Used-Spalte gespeichert werden. Erwarteter Typ: Int64."
Bei C:\Skripte\mbsizereportv6.ps1:281 Zeichen:20
+ $msTable.Rows.add <<<< ($dname,$icount,$tisize,$disize,$quQuota.replace("%","").replace(",",""))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

Any idea?

Anonymous said...

Freakin Awesome script man! Life saver!!!

Anonymous said...

It downloaded and I was able to run it in the shell but nothing seems to happen. I certainly am not getting a gui.

Anonymous said...

Never mind, I was running it in the exchange management shell. When I ran in the Windows Powershell it worked great. Thanks, great tool.

ThinkBSD said...

Is there a way I can see the growth rate in Exchange 2010 ?

Robbie Henry said...

Glen, great tool. I have one issue when I select All servers I get an error on line 68 char 51 Invalid Operation: replace String

David Wilhoit said...

Glen, possible to get the parent folder, or folder path of all the mailbox folders? Specifically I'd like to enumerate the inbox subfolders.

Glen said...

Get-MailboxFolderStatistics will allow you to get all the folders within a mailbox and you should then be able to just filter those that are sub of the Inbox using the Folder Path eg

Get-MailboxFolderStatistics glen | Where-Object {$_.FolderPath -like "/Inbox*"} | select FolderPath

Anonymous said...

Has anyone an idea? I have the same problem

Marcel Gossner said...

This script only partially works on a German Windows SBS 2011:
Ausnahme beim Aufrufen von "Add" mit 1 Argument(en): "Die Eingabezeichenfolge hat das falsche Format.<11.700> konnte n
icht in der Quota Used-Spalte gespeichert werden. Erwarteter Typ: Int64."
Bei C:\Skripte\mbsizereportv6.ps1:281 Zeichen:20
+ $msTable.Rows.add <<<< ($dname,$icount,$tisize,$disize,$quQuota.replace("%","").replace(",",""))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

What i can say is, i can see only mailboxe smaler the 10 MB

Glen Scales said...

Sorry I dont have access to the German version of Exchange to test this but does Bytes get localized into German ? if that the case then the Regex for

$numItempattern = '(?=\().*(?=bytes)'

will fail as its based on the word bytes if you replace it with the localized version that should work

Cheers
Glen

Marcel Gossner said...

The problem must be the different Regional and Language settings. When i change to english, the script works. We use 123'456'789 and english is 123,456,789

Anonymous said...

when I run this against my 2010 exchange server I get no data. both windows empty.

Mustafa Çağrı ÇALIŞKAN said...

Thank you so much

Anonymous said...

I cannot export the growth histroy, it just exports the mailbox grid ?

Anonymous said...

Hi Glen, It appears there's no Button for Exporting the Show Growth History? Can this be fixed as this is an awsome tool and really good to get growth statistics

Martin van Bellen said...

Doesn't seem to work with databases with NO(!) quota...

Anonymous said...

Me too. ??????????????

Guenael RENAUD said...

thank you, you rocks !