Exchange White Space

August 13, 2009


A common posting on PowerShell newsgroups and forums from Exchange administrators is how to parse event id 1221 from the Exchange server application log file. A typical event message would look like:

Event Type:  Information
Event Source: MSExchangeIS Mailbox Store
Event Category: General 
Event ID: 1221
Date:  10/01/2009
Time: 13:27:31
User:  N/A
Computer: SERVER
Description: The database “First Storage Group\Mailbox Store (SERVER)” has
7.2 megabytes of free space after online defragmentation has terminated.

Usual solutions are based on regular expressions to process the message description and extract the name of the database(s) and the number of free megabytes. The bellow code gets the information and doesn’t require any knowledge of regular expression, though I strongly recommend any sys admin getting to know regex!

The message text is a fixed message with two placeholders for the database name and the free megabytes:

  The database “<name>” has “<number>” megabytes of free space after online defragmentation has terminated.

We can access the message placeholder values with the insertion strings array property of the Windows NT event object:

Get-WMIObject Win32_NTLogEvent -ComputerName SERVER -Filter “LogFile=’Application’ AND `
EventCode=1221 AND TimeWritten>=’$Start’ AND TimeWritten<=’$End'” | `
Select-Object ComputerName,InsertionStrings

ComputerName InsertionStrings
———— —————-
SERVER {10351, First Storage Group\SG1 (SERVER)}
SERVER {6043, Second Storage Group\SG2 (SERVER)}
SERVER {881, Third Storage Group\SG3 (SERVER)}

As you can see, the free megs are positioned at index 0 and the database name at 1. With Get-ExchangeWhiteSpace we can pass a computer name and get white space information for the previous day. 

function Get-ExchangeWhiteSpace {

$ComputerName = $(throw ComputerName cannot be empty.)

# Convert Dates to WMI CIM dates
$tc = [System.Management.ManagementDateTimeconverter]
$Start =$tc::ToDmtfDateTime( (Get-Date).AddDays(1).Date )
$End =$tc::ToDmtfDateTime( (Get-Date).Date)

# Create two claculated properties for InsertionStrings values
$DB = @{Name=DB;Expression={$_.InsertionStrings[1]}}
$FreeMB = @{Name=FreeMB;Expression={[int]$_.InsertionStrings[0]}}

Get-WMIObject Win32_NTLogEvent -ComputerName $ComputerName -Filter LogFile=’Application’ AND EventCode=1221 AND TimeWritten>=’$Start’ AND TimeWritten<=’$End’ | Select-Object ComputerName,$DB,$FreeMB | Sort-Object FreeMBUnique Descending



PS > Get-ExchangeWhiteSpace -ComputerName SERVER | Format-Table -AutoSize

ComputerName DB FreeMB
———— — ——
SERVER First Storage Group\SG1(SERVER) 10351
SERVER Second Storage Group\SG2(SERVER) 6043
SERVER Third Storage Group\SG3(SERVER) 881

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



  1. TomAugust 22, 2009 ב 10:55

    Hi Shay,

    Saw your script during a search.

    I could not run this on exchange shell script with an error output. Anything wrong with it?

  2. tomAugust 22, 2009 ב 17:41

    Basically i Copied your script into a *.ps1 file and activated it but nothing comes out. Is there any instruction or compatibility on the powershell to run the script?

    Maybe you can ignore the first post as I used one of the command to run on powershell as within the command has variable.

  3. ScriptFanaticAugust 22, 2009 ב 19:19

    Nothing will happen when you execute the ps1 file you’ve created, you need to call the function. Add this to the end of your ps1 file (after the function declaration) and run the script again:

    Get-ExchangeWhiteSpace -ComputerName

  4. tomAugust 22, 2009 ב 19:32

    I put the “Get-ExchangeWhiteSpace -Computer at the end of ‘}’ function but nothing comes out too?.

  5. ScriptFanaticAugust 22, 2009 ב 20:04

    I guess you don’t have any 1221 events in the log for the specified period of time. Try to change the $Start varibale to -10 days and see if it helps.

  6. tomAugust 22, 2009 ב 20:21

    -10 means 10 hours?

  7. ScriptFanaticAugust 22, 2009 ב 20:46

    $Start sets the starting date to -10 days from the current date.

  8. tomAugust 22, 2009 ב 20:56

    Thanks scriptFanatic. Edited it and it’s working fine now. Just some clarification to make this event more accurate is that when I run this script, it provides alot of similar databases event ID 1221. Is there anyway just to grep the last database offline defragmentation ID 1221?

  9. ScriptFanaticAugust 22, 2009 ב 21:39

    1. Add a third calculated property (convert wmi dates)

      $TimeWritten = @{Name=”TimeWritten”;Expression={ $tc::ToDateTime($_.TimeWritten).ToShortDateString()}}

    2. Change the select+sort command to:

      Select-Object ComputerName,$DB,$FreeMB,$TimeWritten | Sort-Object TimeWritten,FreeMB –Descending

    3. Pipe the reults of the function to where-object and filter by a date  of your choice

      Get-ExchangeWhiteSpace serverName | where {$_.TimeWritten -eq ‘8/21/2009’}

  10. Don VSeptember 30, 2009 ב 22:12

    Great script Shay, but how do I export the output to a csv file?
    Thanks, Don

  11. ScriptFanaticOctober 1, 2009 ב 15:19

    Pipe the command to Export-Csv 🙂

    Get-ExchangeWhiteSpace -ComputerName SERVER | Export-Csv -Path ExWhiteSpace.csv

  12. vbguyOctober 18, 2010 ב 17:41

    Your PS script works great on Exchange 2003 but how can you include VolumeName, TotalSpace,UsedSpace, and FreeSpace then add whitespace to freespace?

  13. NSNovember 10, 2011 ב 10:05

    This may be a dumb question…but who cares if i don’t know its better to ask the expert…
    Can you let me know how to use functions…for eg in the script you’ve written (which btw is lot helpful and thanks for the same)…Lets say there is a script similar to yours…how would you ideally use in your environment…do you copy this script to a .PS1 file or copy it to a different file and save it somewhere?
    How exactly to use this script?

  14. ScriptFanaticNovember 10, 2011 ב 14:02

    @NS, to load the function, either copy and paste the function into your powershell console or put it in a ps1 file and dot-source the file (

  15. JimJanuary 17, 2012 ב 23:51

    Same here doesn’t work.. I tried putting in server name in $computername line .. I tried putting in after you call the function. Appreciate all the work but I wish someone would include an actual example so I see my stupid mistake.

  16. ScriptFanaticJanuary 18, 2012 ב 10:26

    @Jim, copy just the function body (below), change the $ComputerName value to match your server name, and paste it into your console. Do you get anything back?

    $ComputerName = ‘Ex1′

    # Convert Dates to WMI CIM dates
    $tc = [System.Management.ManagementDateTimeconverter]
    $Start =$tc::ToDmtfDateTime( (Get-Date).AddDays(-1).Date )
    $End =$tc::ToDmtfDateTime( (Get-Date).Date)

    # Create two claculated properties for InsertionStrings values
    $DB = @{Name=”DB”;Expression={$_.InsertionStrings[1]}}
    $FreeMB = @{Name=”FreeMB”;Expression={[int]$_.InsertionStrings[0]}}

    Get-WMIObject Win32_NTLogEvent -ComputerName $ComputerName -Filter “LogFile=’Application’ AND EventCode=1221 AND TimeWritten>=’$Start’ AND TimeWritten<='$End'" | Select-Object ComputerName,$DB,$FreeMB | Sort-Object FreeMB –Unique –Descending

  17. JamesMarch 7, 2012 ב 21:24

    This is a great script! It was almost exactly what I was looking for. One minor tweak would make it perfect for me.

    Any easy way to trim the “StorageGroup\” off the database names?

  18. JamesMarch 7, 2012 ב 21:40

    I think I figured it out. I changed the line that reads:
    $DB = @{Name=”DB”;Expression={$_.InsertionStrings[1]}}

    $DB = @{Name=”DB”;Expression={$_.InsertionStrings[1].split(“\”)[1]}}

    Thanks again for a great script.

  19. ScriptFanaticMarch 7, 2012 ב 21:46

    Thanks James. Pipe the results to the Select-Object cmdlet and use a calculated property, split the DB name on ‘\’ and get the last element from the returned array

    Get-ExchangeWhiteSpace | Select-Object *,@{Name=’DB’;Expression={$_.DB.Split(‘\’)[-1]}}

  20. subdtpcck@gmail.comAugust 17, 2013 ב 09:48

    Tunisia is a small country on the southern shores of the Mediterranean; most of its coastline faces eastwards on the Gulf of Gabès.

  21. ishbmpilf@gmail.comAugust 18, 2013 ב 07:52

    had 25 points for the Thunder, but picked up his fourth foul in the third quarter and had to go to the bench when they had seemed to have control of the game.
    [url=]coach outlet[/url]
    coach outlet

  22. jvcujkmkcl@gmail.comAugust 21, 2013 ב 04:07

    Ms. YANAELLE CORNEZ (Manuel’s Tavern Customer):You have no idea how many times I went to a supermarket trying to buy a bottle of wine, coming to the cashier and someone would tell me, ‘No, it’s Sunday, you can’t do that.’

  23. covrypaoqhe@gmail.comAugust 21, 2013 ב 20:27


  24. vfcwgrugsu@gmail.comAugust 26, 2013 ב 23:02

    “It’s a great shame that in 2013 there are still people who are desperate for affirmation. This idea of being accepted by an institution comes from lack of self-acceptance. It’s a shame that some people think their friends and family want to see them married in a church just like everybody else.

  25. arqkaqm@gmail.comAugust 27, 2013 ב 17:27

    “It didn’t swell up real big,” Clark said. “I can walk, I didn’t need crutches, so it feels pretty good. I’ll be ready to go on Friday.”

  26. cheospmtar@gmail.comAugust 27, 2013 ב 17:44

    The rate buffer read control 36 receives the pictures, along with the marker tags and provides them to the VLD 14. As seen in FIG. 5 the tag is carried throughout the decoder to the display processor 28.