Scripting. Powershell, VMware, Windows, Active Directory & Exchange. All that kind of stuff…..
RSS icon Email icon Home icon
  • Using Powershell to Find Free Space in Exchange 2003 databases: Updated

    Posted on May 8th, 2009 Jonathan Medd 5 comments

    Back in January I posted about how to find free space in Exchange 2003 databases using Powershell.  Not long after this we changed our online maintenance schedules resulting in each database not having maintenance every day. The original script was based on the assumption of maintenance happening every day and there being events in the application log for every database in the last 24 hours.

    Consequently I have had to adjust the script so that it would look back a few days to ensure there are logs for each database. This then created an interesting problem because it meant that sometimes you would get back more than one result per database and so obviously you would only want to keep the most recent result.

    For example you would get results like the below:

    ServerName,MailboxStore,”Free Space (MB)”,”Time Written”
    SERVER1,SG1-MAILBOX1,1592,20090423070001.000000+060
    SERVER1,SG1-MAILBOX1,1684,20090422070001.000000+060
    SERVER1,SG1-MAILBOX2,52,20090423070000.000000+060
    SERVER1,SG1-MAILBOX2,64,20090422070000.000000+060
    SERVER1,SG1-MAILBOX3,2607,20090422070001.000000+060
    SERVER1,SG1-MAILBOX3,2566,20090423070000.000000+060

    If I used:

    $myCol | Sort-Object Servername,MailboxStore -unique

    it would produce results with only one entry per mailbox store, but it would always choose the most recent result. So I posted my issue to the PowerShell newsgroup and MVP Marco Shaw very kindly helped me work through it. The end result was this:

    $hash=@{}
    $myCol | Sort-Object @{Expression="Servername";Descending=$false},@{Expression="MailboxStore";Descending=$false},@{Expression="Time Written";Descending=$true} | Foreach-Object {if($hash[$_.mailboxstore] -eq $null){$hash[$_.mailboxstore]=$_}}
    $hash.values
    Marco explains below how this works:
    “Imagine the following simple data:
    PS C:\Users\Marco> gc data.csv
    server,ip
    server1,ip1
    server1,ip2
    server2,ip2
    server2,ip3
    In your case, you have event log entries.  Now, with the above code, you determine you want to only retrieve the first IP listed for each server.  There’s several ways to accomplish this, but with my hash table approach…

    ipcsv data.csv|%{if($hash[$_.server] -eq $null){$hash[$_.server]=$_}}

    So, I create $hash as a hashtable variable.

    I use a foreach-object to look at each object in the collection.  Looking at each object’s server property, I get the current value of the property ($_.server).  I use that as the key for my name/value pair in the hashtable.
    Basically, if we take the first line of the input data where $_.server=”server1″, I take that property, and check if the hashtable already has this name if($hash[$_.server] -eq $null).  If that is true, this is the first occurence of the value “server1″, so I create that hash key with that name and pass $_ as the value.
    When I hit line #2 in the input data, and check $hash[$_.server] again (or $hash["server1"]), I see that name already exists, so I skip it.
    Then onto line #3, where $_.server is now “server2″.
    So from the above, I make sure that for each serverX, I get only the first IP address in the list.

    This is similar to your scenario where you only want the first occurence per mailboxstore.”
    Nice!
    The resulting updated script is below. Note I also updated it somewhat on the original based on a useful technique illustrated in another posting.
    $ExchServer = 'Server1','Server2'
    
    #Get the time 3 days ago in the right format for WMI query
    $WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::Now.AddDays(-3))
    
    $myCol = @()
    foreach ($Server in $ExchServer){
    
        #Perform WMI query of Event 1221 in Application log in the last day
        $eventid = Get-WmiObject -computer $Server -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'")
    
        foreach ($event in $eventid){
    
            #Get the name of the Mailbox Store
            $MBXStoreLocationStart = $event.Message.IndexOf("Storage Group") + 16
            $MBXStoreLocationFinish = $event.Message.IndexOf("has") - 2
            $MBXStoreLocation = $event.Message.SubString($MBXStoreLocationStart, $MBXStoreLocationFinish - $MBXStoreLocationStart)
    
            #Get the free space figure
            $MBLocationStart = $event.Message.IndexOf("has") + 4
            $MBLocationFinish = $event.Message.IndexOf("megabytes") - 1
            $MBLocation = $event.Message.SubString($MBLocationStart, $MBLocationFinish - $MBLocationStart)
    
            #Store the data in $myCol
            $MYInfo = “” | select-Object ServerName,MailboxStore,'Free Space (MB)','Time Written'
            $MYInfo.ServerName = $event.ComputerName
            $MYInfo.MailboxStore = $MBXStoreLocation
            $MYInfo.'Free Space (MB)' = $MBLocation
            $MYInfo.'Time Written' = $event.TimeWritten
            $myCol += $MYInfo
    
        }
    }
    
    $hash=@{}
    $myCol | Sort-Object @{Expression="Servername";Descending=$false},@{Expression="MailboxStore";Descending=$false},@{Expression="Time Written";Descending=$true} |Foreach-Object {if($hash[$_.mailboxstore] -eq $null){$hash[$_.mailboxstore]=$_}}
    $hash.values | Sort-Object Servername,MailboxStore | Export-Csv AllExchangeWhiteSpace.csv -NoTypeInformation

     

    5 responses to “Using Powershell to Find Free Space in Exchange 2003 databases: Updated” RSS icon

    • Jonathan

      you are clearly a clever man with the brain of a planet. Your stuff here is awesome. I am also clever but with the software brain of a squirrel- and even that may be pushing my luck…

      I want what you are writing about but I have not the slightest idea how to turn your magic into a super Twitter for me. I have several thoughts

      One – you have a product to die for that lots of people would like.
      Two – most of us cannot understand how to get it or what all the software stuff means.
      Three- can you tell me how put this all onto my Twitter
      Four – can we make it Glen friendly and then sell it????

      By the way, my eldest son Mark is the crisis software writer for Lloyds shipping insurers in London so at least one of the family has a proper brain!

      regards and thanks

      Glen

    • Jonathan Medd

      Thanks. I presume you are talking about the Twitter PowerPack I made for PowerGUI.

      PowerGUI is a free tool provided by Quest Software. The Twitter PowerPack I made for it is open source and consequently free – the general idea being we all share useful tools to make things better for other people.

      So you are more than welcome to use it, but neither I nor Quest (directly anyway) have any intention of making money from it. To use it you need to install the following.

      1) Windows Powershell which you can get from here: http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx

      2) PowerGUI, which you can get from here: http://www.powergui.org/

      3) Then download and import the Twitter PowerPack from here: http://powergui.org/entry.jspa?externalID=2362&categoryID=21

      I think though something like Thwirl may be more suitable for your own Twitter needs.

      http://www.twhirl.org/

    • Hi Jonathan,
      I was trying to automate this whole activity which was really a time consuming precedure.
      Your script really helped me a lot in automating this!!
      Thanks a TON!! thats indeed a great minds work..

      Thanks
      Hari.

    • No problem, glad you found it useful.

      Jonathan

    • I need to break out the Storage Group name and run and if-then-else on it to make sure we are not pulling in Public Folder storage groups.

      I can’t find much about the “IndexOf” method in PS.


    Leave a reply