Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

AD attribute for user's mailbox size?

Posted on 2006-10-08
22
Medium Priority
?
5,659 Views
Last Modified: 2013-11-19
Hi,

Does anyone know the AD attribute for current user's mailbox size?

I want to export user's AD attributes as well as Exchange related attribute. I can find the AD attributes for user's soft and hard quota, but can not find AD attribute for the current user's mailbox size.  I want to export these informations using a tool such as exporter pro. If I export the mailbox size list into csv using ESM, then it would required lot of work to combine it with the other report I made.


0
Comment
Question by:juragan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 5
  • 2
  • +3
22 Comments
 
LVL 104

Expert Comment

by:Sembee
ID: 17686282
I don't believe the current mailbox size is stored in the domain as it is a variable amount. Exchange reads the quota that is stored in the domain, but doesn't report the size back.

Simon.
0
 
LVL 8

Expert Comment

by:Jejin Joseph
ID: 17686626
Well if your intention is to extract the mailbox size for reporting, this script might help you get that information. http://support.microsoft.com/kb/320071
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17689635

I haven't a clue what Exporter Pro is... But...

Which version of Exchange?

Exchange 2003 has a WMI component that will report the size of all mailboxes on the server. I can show you code for that if you wish.

Chris
0
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 
LVL 2

Author Comment

by:juragan
ID: 17695698
It is a software from SystemTools.com.
I am using Exchange 2003 Enterprise.  Would appreciate if you can show me the code.


0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17697502

Here we go, it's quite long but will create a Tab Delimited Text File (called MailboxSizes.txt) containing all Exchange Users (and a few accidental extra's normally), their mailbox sizes, whether they use the default Store Limits or not (and if they don't what has been set), and the mailbox store they're in.

It also echo's that output so please run the script with CScript of you'll get a hell of a lot of popup boxes. i.e.:

C:\> cscript <ScriptName.vbs>

Finally it creates a summary of how much space is taken up if you were to split stores into alphabetical order as we do (AlphabeticalTotal.txt).

The only thing you need to change is the EXCHANGE_SERVER constant at the beginning (save this as .vbs and make sure you read the opening comment):



' Retrieves information relating to Mailbox Sizes. Must be run as Exchange Administrator and must be run from a
' machine with the Exchange System Tools installed. Only compatible with Exchange 2003.
'
' Author: Chris Dent
' Last Modified: 10/10/2006

Option Explicit

' Global Constants

Const EXCHANGE_SERVER = "<ExhangeServerName>"

' Global Variables

Dim objResults

'
' Functions
'

Function FormatGUID(arrGUID)
      Dim strGUID, strTemp
      Dim i

      For i = LBound(arrGUID) To UBound(arrGUID)
            strTemp = strTemp & Hex(AscB(MidB(arrGUID, i + 1, 1)) \ 16) &_
                  Hex(AscB(MidB(arrGUID, i + 1, 1)) Mod 16)
      Next

      ' Reversed Pairs

      i = 0
      strGUID = "{"
      Do Until i = 8
            strGUID = strGUID & Mid(strTemp, 7 - i, 1)
            strGUID = strGUID & Mid(strTemp, 8 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 12
            strGUID = strGUID & Mid(strTemp, 19 - i, 1)
            strGUID = strGUID & Mid(strTemp, 20 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 16
            strGUID = strGUID & Mid(strTemp, 15 - i + 12, 1)
            strGUID = strGUID & Mid(strTemp, 16 - i + 12, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"

      ' Normal Pairs

      For i = 17 to 20
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "-"
      For i = 21 to 32
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "}"
      FormatGUID = strGUID
End Function

'
' Subroutines
'

Sub GetADData
      Const ADS_SCOPE_SUBTREE = 2

      Dim objConnection, objCommand, objRootDSE, objRecordSet
      Dim strDisplayName, strUseLimits, strLimit, strSize, strStore, strMailboxGUID
      Dim booUseLimits

      Set objConnection = CreateObject("ADODB.Connection")
      objConnection.Provider = "ADsDSOObject"
      objConnection.Open "Active Directory Provider"
      
      Set objCommand = CreateObject("ADODB.Command")
      objCommand.ActiveConnection = objConnection

      Set objRootDSE = GetObject("LDAP://RootDSE")

      objCommand.CommandText = "SELECT displayName, mDBUseDefaults, " &_
                  "mDBStorageQuota, msExchMailboxGUID FROM 'LDAP://" &_
                  objRootDSE.Get("defaultNamingContext") & "' WHERE " &_
                  "objectCategory='CN=Person,CN=Schema," & objRootDSE.Get("configurationNamingContext") & "'"

      Set objRootDSE = Nothing
      
      objCommand.Properties("Page Size") = 1000
      objCommand.Properties("Timeout") = 600
      objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
      objCommand.Properties("Cache Results") = False
      
      Set objRecordSet = objCommand.Execute
      
      While Not objRecordSet.EOF
            If Not IsNull(objRecordSet.Fields("msExchMailboxGUID")) Then
                  strMailboxGUID = FormatGUID(objRecordSet.Fields("msExchMailboxGUID"))
                  
                  If Not objResults.Exists(strMailboxGUID) Then
                        booUseLimits = objRecordSet.Fields("mDBUseDefaults")
                        If booUseLimits = True Then
                              strUseLimits = "True"
                        Else
                              strUseLimits = "False"
                        End If

                        strDisplayName = objRecordSet.Fields("displayName")
                        strLimit = objRecordSet.Fields("mDBStorageQuota")
            
                        objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                    strSize, strStore)
                  End If
            End If
            objRecordSet.MoveNext
      Wend
      
      objConnection.Close
      
      Set objRecordSet = Nothing
      Set objCommand = Nothing
      Set objConnection = Nothing
End Sub

Sub GetMailboxes
      Const WBEM_RETURN_IMMEDIATELY = &h10
      Const WBEM_FORWARD_ONLY = &h20

      Dim objWMIService, objMailbox
      Dim colMailboxes
      Dim strMailboxGUID, strDisplayName, strLimit, strUseLimits, strSize, strStore

      Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")
      Set colMailboxes = objWMIService.ExecQuery("SELECT * FROM Exchange_Mailbox", "WQL",_
                  WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)

      For Each objMailbox In colMailboxes
            If objMailbox.ServerName = EXCHANGE_SERVER Then
                  If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 And _
                              InStr(objMailbox.MailboxDisplayName, "UKEXBE01") = 0 Then

                        strMailboxGUID = objMailbox.MailboxGUID

                        If objResults.Exists(strMailboxGUID) Then
                              strDisplayName = objResults(strMailboxGUID)(0)
                              strLimit = objResults(strMailboxGUID)(1)
                              strUseLimits  = objResults(strMailboxGUID)(2)
                              strSize = objMailbox.Size
                              strStore = objMailbox.StoreName
                        
                              objResults.Remove strMailboxGUID
                              objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                          strSize, strStore)
                        End If
                  End If
            End If
      Next
      
      Set colMailboxes = Nothing
      Set objWMIService = Nothing
End Sub

Sub WriteResults
      Dim objFileSystem, objFile
      Dim strEcho, strLine, strMailboxGUID, strDisplayName, strLimit, strUseLimits, strSize, strStore
      Dim i, intTotal

      Set objFileSystem = CreateObject("Scripting.FileSystemObject")
      Set objFile = objFileSystem.OpenTextFile("MailboxSizes.txt", 2, True, 0)
      
      strLine = "Display Name" & VbTab & "Limit on Account" & VbTab &_
            "Use Limits Enabled" & VbTab & "Size on Server" & VbTab & "Storage Group"
      objFile.WriteLine strLine
      
      For Each strMailboxGUID in objResults
            strDisplayName = objResults(strMailboxGUID)(0)
            strLimit = objResults(strMailboxGUID)(1)
            strUseLimits = objResults(strMailboxGUID)(2)
            strSize = objResults(strMailboxGUID)(3)
            strStore = objResults(strMailboxGUID)(4)
      
            strEcho = strDisplayName & ": " 
            If strUseLimits = False Then
                  strEcho = strEcho & "Limit: " & strLimit & " - "
            End If
            strEcho = strEcho & "Size: " & strSize & " - Store: " & strStore
            WScript.Echo strEcho
      
            strLine = strDisplayName & VbTab & strLimit & VbTab & strUseLimits &_
                  VbTab & strSize & VbTab & strStore
                  
            objFile.WriteLine strLine
      Next
      
      Set objFile = Nothing
      
      Set objFile = objFileSystem.OpenTextFile("AlphabeticalTotal.txt", 2, True, 0)
      For i = 65 to 90
            intTotal = 0
            For Each strMailboxGUID in objResults
                  If Left(objResults(strMailboxGUID)(0), 1) = Chr(i) Then
                        If IsNumeric(objResults(strMailboxGUID)(3)) Then
                              intTotal = intTotal + CDbl(objResults(strMailboxGUID)(3))
                        End If
                  End If
            Next
            objFile.WriteLine Chr(i) & VbTab & intTotal
      Next
End Sub

'
' Main Code
'

Set objResults = CreateObject("Scripting.Dictionary")

GetADData
GetMailboxes
WriteResults

Set objResults = Nothing
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17697516

One more note. All sizes are in Kb as this is how Exchange holds them; I don't convert those anywhere in the script.

Chris
0
 
LVL 104

Expert Comment

by:Sembee
ID: 17697813
Nice script.

Two things...

1. Is UKEXBE01 supposed to be in there?
2. The variable doesn't seem to be right just above it. If I change the Exchange_Server to the server's real name, then remove the " and & then the script runs fine - although doesn't drop dump the mailbox size.

Simon.
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17698839

1. Nope, that would be mine, I forgot to remove it and change it for EXCHANGE_SERVER.

2. Where are you removing those from?

There are only really two important places that use the constant:

Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

And:

If objMailbox.ServerName = EXCHANGE_SERVER Then

For that the EXCHANGE

The rest are pretty meaningless in the scheme of things.

Anyway, that bit must run correctly or it won't pick up the mailbox sizes at all. The mailboxes themselves are matched to the User Accout via the MailboxGUID (which is hopefully clear anyway).

Chris
0
 
LVL 104

Expert Comment

by:Sembee
ID: 17698928
It was this one that I was changing:

    Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

Originally it would generate a cannot find server error.

I can run the script, it picks up the mailboxes, but it doesn't show the size.

Simon.
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17699043

Hey Simon,

There are a couple of things I didn't think of at the time. Mainly because the constant was a last minute addition (it was only for figuring out how we needed to organise our mailbox stores when we move everything over).

First of all:

    Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

When it concatenates the strings including the Constant it must end up with a valid connection string; from the error you're getting the network name is not able to resolve. Can you try replacing that line with:

    Set objWMIService = GetObject("winmgmts:\\SomeExchangeHostName\root\MicrosoftExchangeV2")

Where SomeExchangeHostName is (naturally) the name of your own Exchange Server. Whatever happens it must be able to resolve the hostname.

Then it would perhaps be good to remove one of the If Statements in the loop below for the time-being as it's case sensitive and could easily break the query after the connection is established (which I should have accounted for in the first place).

This is the block of code:

     For Each objMailbox In colMailboxes
          If objMailbox.ServerName = EXCHANGE_SERVER Then
               If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 And _
                         InStr(objMailbox.MailboxDisplayName, "UKEXBE01") = 0 Then

                    strMailboxGUID = objMailbox.MailboxGUID

                    If objResults.Exists(strMailboxGUID) Then
                         strDisplayName = objResults(strMailboxGUID)(0)
                         strLimit = objResults(strMailboxGUID)(1)
                         strUseLimits  = objResults(strMailboxGUID)(2)
                         strSize = objMailbox.Size
                         strStore = objMailbox.StoreName
                   
                         objResults.Remove strMailboxGUID
                         objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                   strSize, strStore)
                    End If
               End If
          End If
     Next

And it should be replaced with:

     For Each objMailbox In colMailboxes
          If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 Then

               strMailboxGUID = objMailbox.MailboxGUID

               If objResults.Exists(strMailboxGUID) Then
                    strDisplayName = objResults(strMailboxGUID)(0)
                    strLimit = objResults(strMailboxGUID)(1)
                    strUseLimits  = objResults(strMailboxGUID)(2)
                    strSize = objMailbox.Size
                    strStore = objMailbox.StoreName
                   
                    objResults.Remove strMailboxGUID
                    objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                              strSize, strStore)
               End If
          End If
     Next

That also removes one of the filters for generally meaningless mailboxes - it'll be easy enough to strip those out with Excel anyway.

I'll repost the script with these edits in a moment so it's not quite so much messing around.

Chris
0
 
LVL 104

Expert Comment

by:Sembee
ID: 17699138
I made the change you outlined already and it partially worked - hence my second comment in my post above.

You left UKEXBE01 in again...

I will wait for you to post the complete code and then I will test it again. I have a couple of sites to work on it for now.

Do you have a web site to share this with the wider community?

Simon.
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17699587

> Do you have a web site to share this with the wider community?

I have the space, I just haven't really got around to documenting all of this sufficiently to add it on there. I'll make a bit of an effort to get it all sorted out at some point.

In the meantime:

I left it in intentionally that time; I figure it's too late to pretend it's not there.

This is the complete code again with some fixes additions (mainly mDBOverQuotaLimit). It won't worry too much about the Name of the server this time as long as it can resolve it to an IP somewhere and actually complete the WMI connection (that's all it's used for). If you're running it from the Exchange Server itself then it can just be ".".

It's still restricted to Exchange 2003 of course, and if it's running from an alternate PC it must be the System Tools for that version (just for the WMI components). As before it must be run as an Exchange Administrator.


' Retrieves information relating to Mailbox Sizes. Must be run as Exchange Administrator and must be run from a
' machine with the Exchange System Tools installed. Only compatible with Exchange 2003.
'
' Author: Chris Dent
' Last Modified: 10/10/2006

Option Explicit

' Global Constants

Const EXCHANGE_SERVER = "ServerName"

' Global Variables

Dim objResults

'
' Functions
'

Function FormatGUID(arrGUID)
      Dim strGUID, strTemp
      Dim i

      For i = LBound(arrGUID) To UBound(arrGUID)
            strTemp = strTemp & Hex(AscB(MidB(arrGUID, i + 1, 1)) \ 16) &_
                  Hex(AscB(MidB(arrGUID, i + 1, 1)) Mod 16)
      Next

      ' Reversed Pairs

      i = 0
      strGUID = "{"
      Do Until i = 8
            strGUID = strGUID & Mid(strTemp, 7 - i, 1)
            strGUID = strGUID & Mid(strTemp, 8 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 12
            strGUID = strGUID & Mid(strTemp, 19 - i, 1)
            strGUID = strGUID & Mid(strTemp, 20 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 16
            strGUID = strGUID & Mid(strTemp, 27 - i, 1)
            strGUID = strGUID & Mid(strTemp, 28 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"

      ' Normal Pairs

      For i = 17 to 20
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "-"
      For i = 21 to 32
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "}"
      FormatGUID = strGUID
End Function

'
' Subroutines
'

Sub GetADData
      Const ADS_SCOPE_SUBTREE = 2

      Dim objConnection, objCommand, objRootDSE, objRecordSet
      Dim strDisplayName, strUseLimits, strSize, strStore, strMailboxGUID
      Dim strWarnLimit, strQuotaLimit
      Dim booUseLimits

      Set objConnection = CreateObject("ADODB.Connection")
      objConnection.Provider = "ADsDSOObject"
      objConnection.Open "Active Directory Provider"
      
      Set objCommand = CreateObject("ADODB.Command")
      objCommand.ActiveConnection = objConnection

      Set objRootDSE = GetObject("LDAP://RootDSE")

      objCommand.CommandText = "SELECT displayName, mDBUseDefaults, " &_
                  "mDBStorageQuota, mDBOverQuotaLimit, msExchMailboxGUID FROM 'LDAP://" &_
                  objRootDSE.Get("defaultNamingContext") & "' WHERE " &_
                  "objectCategory='CN=Person,CN=Schema," & objRootDSE.Get("configurationNamingContext") & "'"

      Set objRootDSE = Nothing
      
      objCommand.Properties("Page Size") = 1000
      objCommand.Properties("Timeout") = 600
      objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
      objCommand.Properties("Cache Results") = False
      
      Set objRecordSet = objCommand.Execute
      
      While Not objRecordSet.EOF
            If Not IsNull(objRecordSet.Fields("msExchMailboxGUID")) Then
                  strMailboxGUID = FormatGUID(objRecordSet.Fields("msExchMailboxGUID"))
                  
                  If Not objResults.Exists(strMailboxGUID) Then
                        booUseLimits = objRecordSet.Fields("mDBUseDefaults")
                        If booUseLimits = True Then
                              strUseLimits = "True"
                        Else
                              strUseLimits = "False"
                        End If

                        strDisplayName = objRecordSet.Fields("displayName")
                        
                        If InStr(1, strDisplayName, "SystemMailbox", VbTextCompare) = 0 Then
                              strWarnLimit = objRecordSet.Fields("mDBStorageQuota")
                              strQuotaLimit = objRecordSet.Fields("mDBOverQuotaLimit")
            
                              objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                          strWarnLimit, strQuotaLimit, strSize, strStore)
                        End If
                  End If
            End If
            objRecordSet.MoveNext
      Wend
      
      objConnection.Close
      
      Set objRecordSet = Nothing
      Set objCommand = Nothing
      Set objConnection = Nothing
End Sub

Sub GetMailboxes
      Const WBEM_RETURN_IMMEDIATELY = &h10
      Const WBEM_FORWARD_ONLY = &h20

      Dim objWMIService, objMailbox
      Dim colMailboxes
      Dim strMailboxGUID, strDisplayName, strUseLimits, strSize, strStore
      Dim strWarnLimit, strQuotaLimit

      Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")
      Set colMailboxes = objWMIService.ExecQuery("SELECT * FROM Exchange_Mailbox", "WQL",_
                  WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)

      For Each objMailbox In colMailboxes
            If InStr(1, objMailbox.MailboxDisplayName, "SystemMailbox", VbTextCompare) = 0 Then

                  strMailboxGUID = objMailbox.MailboxGUID

                  If objResults.Exists(strMailboxGUID) Then
                        strDisplayName = objResults(strMailboxGUID)(0)
                        strUseLimits  = objResults(strMailboxGUID)(1)
                        strWarnLimit = objResults(strMailboxGUID)(2)
                        strQuotaLimit = objResults(strMailboxGUID)(3)
                        strSize = objMailbox.Size
                        strStore = objMailbox.StoreName
                        
                        objResults.Remove strMailboxGUID
                        objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                    strWarnLimit, strQuotaLimit, strSize, strStore)
                  End If
            End If
      Next
      
      Set colMailboxes = Nothing
      Set objWMIService = Nothing
End Sub

Sub WriteResults
      Dim objFileSystem, objFile
      Dim strEcho, strLine, strMailboxGUID, strDisplayName, strUseLimits, strSize, strStore
      Dim strWarnLimit, strQuotaLimit
      Dim i, intTotal

      Set objFileSystem = CreateObject("Scripting.FileSystemObject")
      Set objFile = objFileSystem.OpenTextFile("MailboxSizes.txt", 2, True, 0)
      
      strLine = "Display Name" & VbTab & "Use Limits Enabled" & VbTab & "Warning Limit" &_
            VbTab & "Quota Limit" & VbTab & "Size on Server" & VbTab & "Storage Group"
      objFile.WriteLine strLine
      
      For Each strMailboxGUID in objResults
            strDisplayName = objResults(strMailboxGUID)(0)
            strUseLimits = objResults(strMailboxGUID)(1)
            strWarnLimit = objResults(strMailboxGUID)(2)
            strQuotaLimit = objResults(strMailboxGUID)(3)
            strSize = objResults(strMailboxGUID)(4)
            strStore = objResults(strMailboxGUID)(5)
      
            strEcho = strDisplayName & ": "
            If strUseLimits = "False" Then
                  strEcho = strEcho & "Warning Limit: " & strWarnLimit & " | Quota Limit: " &_
                        strQuotaLimit & " - "
            End If
      
            strEcho = strEcho & "Size: " & strSize & " - Store: " & strStore
            WScript.Echo strEcho
            
            strLine = strDisplayName & VbTab & strUseLimits & VbTab & strWarnLimit &_
                        VbTab & strQuotaLimit & VbTab & strSize & VbTab & strStore
                  
            objFile.WriteLine strLine
      Next
      
      Set objFile = Nothing
      
      Set objFile = objFileSystem.OpenTextFile("AlphabeticalTotal.txt", 2, True, 0)
      For i = 65 to 90
            intTotal = 0
            For Each strMailboxGUID in objResults
                  If Left(objResults(strMailboxGUID)(0), 1) = Chr(i) Then
                        If IsNumeric(objResults(strMailboxGUID)(4)) Then
                              intTotal = intTotal + CDbl(objResults(strMailboxGUID)(4))
                        End If
                  End If
            Next
            objFile.WriteLine Chr(i) & VbTab & intTotal
      Next
End Sub

'
' Main Code
'

Set objResults = CreateObject("Scripting.Dictionary")

GetADData
GetMailboxes
WriteResults

Set objResults = Nothing

0
 
LVL 104

Expert Comment

by:Sembee
ID: 17699710
Voilà. Works beautifully. Hopefully juragan will notice as well.

Simon.
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17699722

Excellent :)

Chris
0
 
LVL 2

Author Comment

by:juragan
ID: 17713604
Thanks for the script, Chris.

I have 4 Exchange servers in my network, and I ran the script with 'Server_1' for the Server Name variable.

The script dumped the listing on the Command Prompt box, as well as created two .txt files.  I opened the file mailboxsizes.txt and noticed that it contains ALL mailboxes from ALL servers, however only users from SERVER have the fields 'Size on Server' and 'Storage Group' filled in.

Did I miss anything?
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 17713635

Nope you didn't. It only lists mailboxes for the server it's directly running against. Hold on a moment and I'll add some bits in tol get around that.

Chris
0
 
LVL 71

Accepted Solution

by:
Chris Dent earned 500 total points
ID: 17714440

Right, here we go. It's a little more complicated this time (and a fair bit longer), I've tried to ensure that there is nothing in the script that you need to alter (the constant from before it gone now) and naturally I've run and re-run it to at least attempt to ensure it's error free.

You do need to tell it what you want to do, those are command line parameters. It'll echo the usage instructions if you don't set them properly. I'm not sure how your Exchange organisation is configured, but I would assume you want to run it with:

cscript GetMailboxSizes.vbs -a -f "Report.txt"

Which will list mailbox sizes for all mailboxes on all servers within the First Administrative Group (renamed or otherwise). If it's not so simple then you would possibly need:

cscript GetMailboxSizes.vbs -a "Your Administrative Group" -f "Report.txt"

The other options are for a Single Server (-s <ServerName>) or for the entire Organisation (-o). There is another switch that can be used with -o which will temporarily reset the DNS Suffix Search List on the machine running the script to help it form the WMI connection to each Exchange Server in the organisation.

An organisation-wide search is likely to take a long time and I haven't tested it extensively (beyond ensuring that it returns all the servers correctly and will at least work in theory).

On the reporting side there's -f and -l, -f is the regular file report and you'll need to specify the filename. -l is the list based on the first letter of the display name (for us that's surname) and just a summary of sizes under those letters; as with -f you need to specify the filename.

It's entirely possible to add far more in the way of user filtering to the script - I haven't right now because it's quite long enough for the moment.

I really hope I've managed to remove every single bug otherwise writting corrections will be quite messy ;)

See how you get on with this:



' GetMailboxSizes.vbs
'
' Retrieves information relating to Mailbox Sizes. Must be run as Exchange Administrator and must be run from a
' machine with the Exchange System Tools installed. Only compatible with Exchange 2003.
'
' Author: Chris Dent
' Last Modified: 12/10/2006

Option Explicit

'
' Functions
'

Function FormatGUID(arrGUID)
      Dim strGUID, strTemp
      Dim i

      For i = LBound(arrGUID) To UBound(arrGUID)
            strTemp = strTemp & Hex(AscB(MidB(arrGUID, i + 1, 1)) \ 16) &_
                  Hex(AscB(MidB(arrGUID, i + 1, 1)) Mod 16)
      Next

      ' Reversed Pairs

      i = 0
      strGUID = "{"
      Do Until i = 8
            strGUID = strGUID & Mid(strTemp, 7 - i, 1)
            strGUID = strGUID & Mid(strTemp, 8 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 12
            strGUID = strGUID & Mid(strTemp, 19 - i, 1)
            strGUID = strGUID & Mid(strTemp, 20 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 16
            strGUID = strGUID & Mid(strTemp, 27 - i, 1)
            strGUID = strGUID & Mid(strTemp, 28 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"

      ' Normal Pairs

      For i = 17 to 20
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "-"
      For i = 21 to 32
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "}"
      FormatGUID = strGUID
End Function

Function GetForestContexts
      ' Returns a array containing all Domains (Distinguished Name) in the active Forest

      Dim objRootDSE, objForestRoot
      Dim strForestRoot, strSubDomain
      Dim arrDomainDNs(), arrTemp

      Set objRootDSE = GetObject("LDAP://RootDSE")
      strForestRoot = objRootDSE.Get("rootDomainNamingContext")
      Set objForestRoot = GetObject("LDAP://" & strForestRoot)

      ReDim Preserve arrDomainDNs(0)
      arrDomainDNs(0) = strForestRoot

      ' Rebuild Domains List removing the DNS and Configuration contexts

      arrTemp = objForestRoot.Get("subRefs")
      For Each strSubDomain in arrTemp
            If (InStr(strSubDomain, "DnsZones") = 0) And (InStr(strSubDomain, "Configuration") = 0) Then
                  ReDim Preserve arrDomainDNs(UBound(arrDomainDNs) + 1)
                  arrDomainDNs(UBound(arrDomainDNs)) = strSubDomain
            End If
      Next

      Set objForestRoot = Nothing
      Set objRootDSE = Nothing
      
      GetForestContexts = arrDomainDNs
End Function

Function ConvertToDNS(arrDomainDNs)
      ' Converts Distinguished Names to DNS Names

      Dim strDN, strDomainName
      Dim arrDomainNames()
      Dim i
      
      i = 0
      For Each strDN in arrDomainDNs
            ReDim Preserve arrDomainNames(i)
            strDomainName = Replace(strDN, ",DC=", ".")
            strDomainName = Replace(strDomainName, "DC=", "")
            arrDomainNames(i) = strDomainName
            i = i + 1
      Next
      
      ConvertToDNS = arrDomainNames
End Function

Function GetExchangeServers(strAdminGroup)
      Dim objRootDSE, objExchangeService, objContainer, objAdministrativeGroups, objAdministrativeGroup
      Dim objServers, objServer
      Dim strOrganisationPath, strAdminGroupDisplayName, strAdminGroupName
      Dim arrServers()
      Dim i

      Set objRootDSE = GetObject("LDAP://RootDSE")
      Set objExchangeService = GetObject("LDAP://CN=Microsoft Exchange,CN=Services," &_
                  objRootDSE.Get("configurationNamingContext"))
      Set objRootDSE = Nothing
      For Each objContainer in objExchangeService
            If objContainer.Class = "msExchOrganizationContainer" Then
                  strOrganisationPath = objContainer.Get("distinguishedName")
            End If
      Next
      Set objExchangeService = Nothing

      i = 0

      On Error Resume Next
      Set objAdministrativeGroups = GetObject("LDAP://CN=Administrative Groups," & strOrganisationPath)
      For Each objAdministrativeGroup in objAdministrativeGroups
            strAdminGroupDisplayName = "" : strAdminGroupDisplayName = objAdministrativeGroup.Get("displayName")
            strAdminGroupName = "" : strAdminGroupName = objAdministrativeGroup.Get("name")
      
            If LCase(strAdminGroupName) = strAdminGroup Or _
                        (LCase(strAdminGroupDisplayName) = strAdminGroup And _
                        strAdminGroupDisplayName <> "") Or _
                        strAdminGroup = "" Then

                        Set objServers = GetObject("LDAP://CN=Servers," & objAdministrativeGroup.Get("distinguishedName"))
                        For Each objServer in objServers
                              ReDim Preserve arrServers(i)
                              arrServers(i) = objServer.Get("name")
                              i = i + 1
                        Next
                        Set objServers = Nothing
            End If
      Next
      Set objAdministativeGroups = Nothing
      On Error Goto 0
      
      GetExchangeServers = arrServers
End Function

'
' Subroutines
'

'
' Usage & Argument Sorting
'

Sub UsageText
      Dim strMessage

      strMessage = "Usage:" & VbCrLf & VbCrLf
      strMessage = strMessage & "cscript " & WScript.ScriptName & " [-s <Server Name>] " & VbCrLf
      strMessage = strMessage & VbTab & "[-a {<Administrative Group Name>}] [-o] [-r] [-f <Filename>]" & VbCrLf
      strMessage = strMessage & VbTab & "[-l <Filename>]" & VbCrLf
      strMessage = strMessage & VbCrLf
      strMessage = strMessage & VbTab & "-s - List Sizes for Mailboxes on the specified Server" & VbCrLf
      strMessage = strMessage & VbTab & "-a {<Administrative Group Name>} - List Sizes for Mailboxes within" & VbCrLf
      strMessage = strMessage & VbTab & "the specified Administrative Group" & VbCrLf & VbCrLf
      strMessage = strMessage & VbTab & VbTab & "If no Administrative Group is specified the First " & VbCrLf
      strMessage = strMessage & VbTab & VbTab & "Administrative Group is used (even if renamed)" & VbCrLf & VbCrLf
      strMessage = strMessage & VbTab & "-o - List Sizes for Mailboxes within the Entire Organisation" & VbCrLf & VbCrLf
      strMessage = strMessage & VbTab & VbTab & "Organisation wide search may take a long time and includes " & VbCrLf
      strMessage = strMessage & VbTab & VbTab & "searching the Global Catalog for Mail Enabled Users" & VbCrLf & VbCrLf
      strMessage = strMessage & VbTab & "-r - When used with -o this will temporarily Reset the DNS Suffix " & VbCrLf
      strMessage = strMessage & VbTab & "Search List on the Machine running the request to ensure all servers " & VbCrLf
      strMessage = strMessage & VbTab & "within the Forest are accessible." & VbCrLf
      strMessage = strMessage & VbTab & "-f <Filename> - Writes report to a File instead of the Console" & VbCrLf
      strMessage = strMessage & VbTab & "-l <Filename> - Writes a list of Store Usage by Alphabetical Order" & VbCrLf
      strMessage = strMessage & VbCrLf & "Note: This Script must be run as Exchange Administrator for the Servers " & VbCrLf
      strMessage = strMessage & "you wish to query. It will only function with Exchange 2003." & VbCrLf
      WScript.Echo strMessage
      WScript.Quit
End Sub

Sub SortArgv
      Dim objArgv, objRootDSE
      Dim strArgv
      Dim i, j, intServerName, intAdminGroup, intOrganisation, intFileName, intSummaryFile

      Set objArgv = WScript.Arguments
      If objArgv.Count < 1 Then
            UsageText()
      End If

      booServerName = False : booAdminGroup = False : booOrganisation = False
      booResetSuffixes = False : booWriteToFile = False : booWriteSummary = False
      i = 0 : j = 0
      For Each strArgv in objArgv
            i = i + 1
            If LCase(strArgv) = "-s" Then
                  booServerName = True
                  intServerName = i
                  j = j + 1
            End If
            If LCase(strArgv) = "-a" Then
                  booAdminGroup = True
                  intAdminGroup = i
                  j = j + 1
            End If
            If LCase(strArgv) = "-o" Then
                  booOrganisation = True
                  j = j + 1
            End If
            If LCase(strArgv) = "-r" Then
                  booResetSuffixes = True
            End If
            If LCase(strArgv) = "-f" Then
                  booWriteToFile = True
                  intFileName = i
            End If
            If LCase(strArgv) = "-l" Then
                  booWriteSummary = True
                  intSummaryFile = i
            End If
      Next

      If j = 0 Or j > 1 Then
            UsageText()
      End If

      If booServerName = True Then
            If objArgv.Count < (intServerName +  1) Then
                  UsageText()
            Else
                  strServerName = objArgv(intServerName)
            End If
      End If
      
      If booAdminGroup = True Then
            If objArgv.Count < (intAdminGroup +  1) Then
                  strAdminGroup = "first administrative group"
            Else
                  If LCase(objArgv(intAdminGroup)) = "-f" Or LCase(objArgv(intAdminGroup) = "-l") Then
                        strAdminGroup = "first administrative group"
                  Else
                        strAdminGroup = LCase(objArgv(intAdminGroup))
                  End If
            End If
      End If
      
      Set objRootDSE = GetObject("LDAP://RootDSE")
      If booOrganisation = True Then
            strDomainName = objRootDSE.Get("rootDomainNamingContext")
      Else
            strDomainName = objRootDSE.Get("defaultNamingContext")
      End If
      Set objRootDSE = GetObject("LDAP://RootDSE")

      If booResetSuffixes = True And booOrganisation = False Then
            UsageText()
      End If

      If booWriteToFile = True Then
            If objArgv.Count < (intFilename + 1) Then
                  UsageText()
            Else
                  If LCase(objArgv(intFilename)) = "-l" Then
                        UsageText()
                  Else
                        strFileName = objArgv(intFilename)
                  End If
            End If
      End If
      
      If booWriteSummary = True Then
            If objArgv.Count < (intSummaryFile + 1) Then
                  UsageText()
            Else
                  If LCase(objArgv(intSummaryFile)) = "-f" Then
                        UsageText()
                  Else
                        strSummaryFile = objArgv(intSummaryFile)
                  End If
            End If
      End If
      
      Set objArgv = Nothing      
End Sub

'
' Network Adapter
'

Function SetSuffixes(arrDomainNames)
      ' Convert DNS Domain Names to Suffixes and check against IP Configuration
      ' Just works better with these set

      Const REG_HKLM = &H80000002

      Dim objRegistry, objShell
      Dim strKeyPath, strValueName, strSuffixes, strDomainName, strOldSuffixes
      Dim booSetSuffixes

      Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
      strKeyPath = "System\CurrentControlSet\Services\TCPIP\Parameters"
      strValueName = "SearchList"
      objRegistry.GetStringValue REG_HKLM, strKeyPath, strValueName, strOldSuffixes

      For Each strDomainName in arrDomainNames
            If InStr(1, strOldSuffixes, strDomainName, VbTextCompare) = 0 Then
                  booSetSuffixes = True
            End If
      Next

      If booSetSuffixes = True Then
            For Each strDomainName in arrDomainNames
                  strSuffixes = strSuffixes & "," & strDomainName
            Next
            strSuffixes = Right(strSuffixes, Len(strSuffixes) - 1)
            objRegistry.SetStringValue REG_HKLM, strKeyPath, strValueName, strSuffixes
            WScript.Echo strSuffixes
            Set objShell = CreateObject("WScript.Shell")
            objShell.Run "ipconfig /renew"
            Set objShell = Nothing
      End If

      Set objRegistry = Nothing
      
      SetSuffixes = strOldSuffixes
End Function

Sub ResetSuffixes(strSuffixes)
      ' Puts the orignal Suffix Search List back

      Const REG_HKLM = &H80000002

      Dim objRegistry, objShell
      Dim strKeyPath, strValueName, strNewSuffixes

      Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
      strKeyPath = "System\CurrentControlSet\Services\TCPIP\Parameters"
      strValueName = "SearchList"

      objRegistry.GetStringValue REG_HKLM, strKeyPath, strValueName, strNewSuffixes
      If strNewSuffixes <> strSuffixes Then
            objRegistry.SetStringValue REG_HKLM, strKeyPath, strValueName, strSuffixes
            Set objShell = CreateObject("WScript.Shell")
            objShell.Run "ipconfig /renew"
            Set objShell = Nothing
      End If
      Set objRegistry = Nothing
End Sub

'
' AD Query
'

Sub GetADData
      Const ADS_SCOPE_SUBTREE = 2

      Dim objConnection, objCommand, objRootDSE, objRecordSet
      Dim strDisplayName, strUseLimits, strSize, strStore, strMailboxGUID
      Dim strWarnLimit, strQuotaLimit, strServer, strPort, strFields
      Dim booUseLimits

      Set objConnection = CreateObject("ADODB.Connection")
      objConnection.Provider = "ADsDSOObject"
      objConnection.Open "Active Directory Provider"
      
      Set objCommand = CreateObject("ADODB.Command")
      objCommand.ActiveConnection = objConnection

      strPort = "LDAP"
      If booOrganisation = True Then
            strPort = "GC"
      End If
      strFields = "displayName, msExchMailboxGUID, mDBUseDefaults, mDBStorageQuota, " &_
                  "mDBOverQuotaLimit, msExchHomeServerName"

      Set objRootDSE = GetObject("LDAP://RootDSE")
      objCommand.CommandText = "SELECT " & strFields & " FROM '" & strPort & "://" & strDomainName & "' WHERE " &_
                  "objectCategory='CN=Person,CN=Schema," & objRootDSE.Get("configurationNamingContext") & "'"
      Set objRootDSE = Nothing
      
      objCommand.Properties("Page Size") = 1000
      objCommand.Properties("Timeout") = 600
      objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
      objCommand.Properties("Cache Results") = False
      
      Set objRecordSet = objCommand.Execute
      
      While Not objRecordSet.EOF
            If Not IsNull(objRecordSet.Fields("msExchMailboxGUID")) Then
                  strMailboxGUID = FormatGUID(objRecordSet.Fields("msExchMailboxGUID"))
                  
                  strUseLimits = "" : strWarnLimit = "" : strQuotaLimit = ""
                  If Not objResults.Exists(strMailboxGUID) Then
                        booUseLimits = objRecordSet.Fields("mDBUseDefaults")
                        strWarnLimit = objRecordSet.Fields("mDBStorageQuota")
                        strQuotaLimit = objRecordSet.Fields("mDBOverQuotaLimit")
                        strServer = objRecordSet.Fields("msExchHomeServerName")
                        strServer = Right(strServer, Len(strServer) - InStr(strServer, "cn=Servers/cn=") - 13)
                        If booUseLimits = True Then
                              strUseLimits = "True"
                        Else
                              strUseLimits = "False"
                        End If

                        strDisplayName = objRecordSet.Fields("displayName")
                        
                        If InStr(1, strDisplayName, "SystemMailbox", VbTextCompare) = 0 Then
                              objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                          strWarnLimit, strQuotaLimit, strSize, strServer, strStore)
                        End If
                  End If
            End If
            objRecordSet.MoveNext
      Wend
      
      objConnection.Close
      
      Set objRecordSet = Nothing
      Set objCommand = Nothing
      Set objConnection = Nothing
End Sub

'
' Exchange Query
'

Sub GetMailboxes(strServerName)
      Const WBEM_RETURN_IMMEDIATELY = &h10
      Const WBEM_FORWARD_ONLY = &h20

      Dim objWMIService, objMailbox
      Dim colMailboxes
      Dim strMailboxGUID, strDisplayName, strUseLimits, strSize, strServer, strStore
      Dim strWarnLimit, strQuotaLimit

      On Error Resume Next
      Err.Clear
      Set objWMIService = GetObject("winmgmts:\\" & strServerName & "\root\MicrosoftExchangeV2")
      Set colMailboxes = objWMIService.ExecQuery("SELECT * FROM Exchange_Mailbox", "WQL",_
                  WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)

      If Err.Number <> 0 Then
            Exit Sub
      End If
       On Error Goto 0

      For Each objMailbox In colMailboxes
            If InStr(1, objMailbox.MailboxDisplayName, "SystemMailbox", VbTextCompare) = 0 Then
      
                  strMailboxGUID = objMailbox.MailboxGUID

                  If objResults.Exists(strMailboxGUID) Then
                        strDisplayName = objResults(strMailboxGUID)(0)
                        strUseLimits  = objResults(strMailboxGUID)(1)
                        strWarnLimit = objResults(strMailboxGUID)(2)
                        strQuotaLimit = objResults(strMailboxGUID)(3)
                        strServer = objResults(strMailboxGUID)(5)
                        strSize = objMailbox.Size
                        strStore = objMailbox.StoreName
                        
                        objResults.Remove strMailboxGUID
                        objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                    strWarnLimit, strQuotaLimit, strSize, strServer, strStore)
                  End If
            End If
      Next
      
      Set colMailboxes = Nothing
      Set objWMIService = Nothing
End Sub

Sub CleanResults
      Dim strMailboxGUID

      For Each strMailboxGUID in objResults
            If objResults(strMailboxGUID)(4) = "" Then
                  objResults.Remove(strMailboxGUID)
            End If
      Next
End Sub

Sub WriteResults
      Dim objFileSystem, objFile
      Dim strEcho, strLine, strMailboxGUID, strDisplayName, strUseLimits, strSize, strStore
      Dim strServer, strWarnLimit, strQuotaLimit
      Dim i, intTotal

      Set objFileSystem = CreateObject("Scripting.FileSystemObject")

      If booWriteToFile = True Then
            Set objFile = objFileSystem.OpenTextFile(strFileName, 2, True, 0)
      
            strLine = "Display Name" & VbTab & "Use Limits Enabled" & VbTab & "Warning Limit" &_
                  VbTab & "Quota Limit" & VbTab & "Size on Server" & VbTab & "Server Name" & VbTab & "Storage Group"
            objFile.WriteLine strLine
      End If
      
      For Each strMailboxGUID in objResults
            strDisplayName = objResults(strMailboxGUID)(0)
            strUseLimits = objResults(strMailboxGUID)(1)
            strWarnLimit = objResults(strMailboxGUID)(2)
            strQuotaLimit = objResults(strMailboxGUID)(3)
            strSize = objResults(strMailboxGUID)(4)
            strServer = objResults(strMailboxGUID)(5)
            strStore = objResults(strMailboxGUID)(6)
      
            If booWriteToFile = False Then
                  strEcho = strDisplayName & ": "
                  If strUseLimits = "False" Then
                        strEcho = strEcho & "Warning Limit: " & strWarnLimit & " | Quota Limit: " &_
                              strQuotaLimit & " - "
                  End If

                  strEcho = strEcho & "Size: " & strSize & " - Store: " & strStore
                  WScript.Echo strEcho
            End If
            
            If booWriteToFile = True Then
                  strLine = strDisplayName & VbTab & strUseLimits & VbTab & strWarnLimit &_
                              VbTab & strQuotaLimit & VbTab & strSize & VbTab & strServer & VbTab & strStore
                  objFile.WriteLine strLine
            End If
      Next
      If booWriteToFile = True Then
            Set objFile = Nothing
      End If
      
      If booWriteSummary = True Then
            Set objFile = objFileSystem.OpenTextFile(strSummaryFile, 2, True, 0)
            For i = 65 to 90
                  intTotal = 0
                  For Each strMailboxGUID in objResults
                        If Left(objResults(strMailboxGUID)(0), 1) = Chr(i) Then
                              If IsNumeric(objResults(strMailboxGUID)(4)) Then
                                    intTotal = intTotal + CDbl(objResults(strMailboxGUID)(4))
                              End If
                        End If
                  Next
                  objFile.WriteLine Chr(i) & VbTab & intTotal
            Next
      End If
      
      Set objFileSystem = Nothing
End Sub

'
' Main Code
'

' Global Variables

Dim objResults
Dim strServerName, strAdminGroup, strDomainName, strFileName, strSuffixes, strSummaryFile
Dim arrServerNames, arrForestDNs, arrForestDomains
Dim booServerName, booAdminGroup, booOrganisation, booResetSuffixes, booWriteToFile, booWriteSummary

SortArgv

Set objResults = CreateObject("Scripting.Dictionary")

GetADData

If booResetSuffixes = True And booOrganisation = True Then
      arrForestDNs = GetForestContexts
      arrForestDomains = ConvertToDNS(arrForestDNs)
      strSuffixes = SetSuffixes(arrForestDomains)
End If

If booServerName = True Then
      GetMailboxes(strServerName)
ElseIf booAdminGroup = True Then
      arrServerNames = GetExchangeServers(strAdminGroup)
      For Each strServerName in arrServerNames
            GetMailboxes(strServerName)
      Next
ElseIf booOrganisation = True Then
      arrServerNames = GetExchangeServers("")
      For Each strServerName in arrServerNames
            GetMailboxes(strServerName)
      Next
End If

If booResetSuffixes = True And booOrganisation = True Then
      ResetSuffixes strSuffixes
End If

CleanResults
WriteResults

Set objResults = Nothing
0
 

Expert Comment

by:CLRRI
ID: 24317042
I used this solution and it worked great!  Thanks.
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 24318334

It's quite old and has been updated a fair bit since. I'm happier with my update / rewrite here:

http://www.highorbit.co.uk/?p=604

It reports in rather more detail without much of the complexity I have above. The only significant part I dropped was writing the report to the screen, writing to a file is just much neater.

Chris
0
 
LVL 23

Expert Comment

by:Stacy Spear
ID: 33823846
Chris,

Awesome PowerShell script linked through your link above!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

New style of hardware planning for Microsoft Exchange server.
Here in this article, you will get a step by step guidance on how to restore an Exchange database to a recovery database. Get a brief on Recovery Database and how it can be used to restore Exchange database in this section!
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
Suggested Courses

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question