Active Directory and WMI: VBscript to enumerate a sorted list of all mailboxes and their size in your AD domain

Posted May 17th, 2011 in email by dirk adamsky

Today’s script is made for Gavin.
It is an extension of my previous script to enumerate all Exchange mailboxes and their size.
Gavin asked for a sorted list based on mailbox size.

My first attempt was to use the VB Arraylist object (.Net needed on the script machine).
Here’s an Arraylist example by Rob van der Woude.
The problem with the Arraylist object is that it is not made for sorting multi dimensional arrays.
I can do some tricks by concatenating all values to a superstring.
The problem is that sorting an Arraylist with superstrings will be next to impossible.

Luckily I found a better solution by using a disconnected recordset
(= a recordset without database connection).
One thing to check is to use the right datatype for each variable.
I declared the “size” variable as a “double precision floating point”.
The other 2 were delared as “null-terminated character strings”.
With the disconnected recordset you can do a lot of funky stuff like sorting, filtering and so on.
I will certainly use the disconnected recordset object in new scripts.

I have tested the script in a large environment (~ 8500 mailboxes).
It worked flawless (okay I had to test and modify it for half an hour or so).

What the script does:

  • get all exchange servers from your AD domain
  • make a wmi connection to each server and create a list of the mailboxes and their size
  • put all values in a disconnected recordset, sort and output to the screen

The script is tested in a win2003/exchange2003 environment.

Follow the next steps to run the script (admin rights needed):

  • copy and paste the script in your favorite text editor
  • save the script (for example c:tempsortedlistofallmailboxes.vbs)
  • open a command prompt
  • go to “c:temp”
  • give “cscript sortedlistofallmailboxes.vbs” (without quotes) and enter

The script:

' Name : sortedlistofallmailboxes.vbs
' Description : script to enumerate all mailboxes and their size in your AD domain
' Author : dirk adamsky - deludi bv
' Version : 1.00
' Date : 17-05-2011
' Level: intermediate

Set DataList = CreateObject("ADOR.Recordset")
DataList.Fields.Append "Servername", 200, 255
DataList.Fields.Append "DisplayName", 200, 255
DataList.Fields.Append "Size", 5
DataList.Open

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

Set objRootDSE = GetObject("LDAP://RootDSE")
strBase = "<LDAP://" & objRootDSE.Get("configurationnamingcontext") & ">"
strFilter = "(objectCategory=msExchExchangeServer)"
strAttributes = "name"

strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 3
adoCommand.Properties("Cache Results") = False

Set adoRecordset = adoCommand.Execute

Do Until adoRecordset.EOF
 Set objWMIExchange = GetObject("winmgmts:{impersonationLevel=impersonate}!//"&_
 adoRecordset.Fields("name").Value & "/root/MicrosoftExchangeV2")
 Set colExchangeMailboxes = objWMIExchange.InstancesOf("Exchange_Mailbox")
 For Each objExchangeMailbox in colExchangeMailboxes
 If Left(objExchangeMailbox.StorageGroupName, 5) <> "Recov" Then
 DataList.AddNew
 DataList("Servername") = adoRecordset.Fields("name").Value
 DataList("DisplayName") = objExchangeMailbox.MailboxDisplayName
 DataList("Size") = Round(objExchangeMailbox.Size/1024,0)
 Datalist.Update
 End If
 Next
 Set colExchange_Mailboxes = Nothing
 Set objWMIExchange = Nothing
 adoRecordset.MoveNext
Loop

adoRecordset.Close
adoConnection.Close

Set adoRecordset = Nothing
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing

DataList.Sort = "Size DESC"
DataList.MoveFirst

Do Until DataList.EOF
 Wscript.Echo DataList.Fields.Item("Size") & " MB ; " & DataList.Fields.Item("DisplayName") & " ; " &_
 DataList.Fields.Item("Servername")
 DataList.MoveNext
Loop

Datalist.Close
Set DataList = Nothing

When you have problems/questions please post a reply or give a ‘star’ rating.

Happy scripting.

Best regards,

Dirk Adamsky – Deludi BV

Active Directory and WMI: VBscript to show the size of a specific mailbox

Posted May 18th, 2010 in active directory, exchange, vbscript, wmi by dirk adamsky

Today I made a script as requested by Jamal.
It is a further development of a script to enumerate all exchange mailboxes and their size which can be found here.

What the script does:

  • ask for the smtp address of the mailbox
  • get the displayname and homembd properties of that mailbox
  • enumerate all exchange servers
  • make a wmi connection with the exchange server on which the mailbox resides
  • get the size of the mailbox

The script is tested in an win2003/exchange2003 environment.

Follow the next steps to run the script (admin rights needed):

  • copy and paste the script in your favorite text editor
  • save the script (for example c:tempmailboxsize.vbs)
  • open a command prompt
  • go to “c:temp”
  • give “cscript mailboxsize.vbs” (without quotes) and enter

The script:

' Name : mailboxsize.vbs
' Description : script to show the size of a specific mailbox
' Author : dirk adamsky - deludi bv
' Version : 1.00
' Date : 18-05-2010
' Level: advanced

Dim strDisplayName, strHomeMDB
strSMTP = InputBox("Please fill in the SMTP address of the user")
GetDisplayNameAndHomeMDB(strSMTP)

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

Set objRootDSE = GetObject("LDAP://RootDSE")
strBase = "<LDAP://" & objRootDSE.Get("configurationnamingcontext") & ">"
strFilter = "(objectCategory=msExchExchangeServer)"
strAttributes = "name"

strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

Set adoRecordset = adoCommand.Execute

Do Until adoRecordset.EOF
	If Instr(strHomeMDB,adoRecordset.Fields("name").Value) > 1 Then
		Set objWMIExchange = GetObject("winmgmts:{impersonationLevel=impersonate}!//"&_
		adoRecordset.Fields("name").Value & "/root/MicrosoftExchangeV2")
		Set colExchangeMailboxes = objWMIExchange.ExecQuery("Select * From Exchange_Mailbox Where MailboxDisplayName = '" & strDisplayName & "'")
		For Each objExchangeMailbox in colExchangeMailboxes
			If Left(objExchangeMailbox.StorageGroupName, 5) <> "Recov" Then
				Wscript.Echo adoRecordset.Fields("name").Value & " ; " & objExchangeMailbox.MailboxDisplayName & " ; " &_
				Round(objExchangeMailbox.Size/1024,0) & " MB"
			End If
		Next
		Set colExchange_Mailboxes = Nothing
		Set objWMIExchange = Nothing
	End If
	adoRecordset.MoveNext
Loop

adoRecordset.Close
adoConnection.Close

Set adoRecordset = Nothing
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing

Function GetDisplayNameAndHomeMDB(strMail)
	Set adoCommand = CreateObject("ADODB.Command")
	Set adoConnection = CreateObject("ADODB.Connection")
	adoConnection.Provider = "ADsDSOObject"
	adoConnection.Open "Active Directory Provider"
	adoCommand.ActiveConnection = adoConnection

	Set objRootDSE = GetObject("LDAP://RootDSE")
	strDNSDomain = objRootDSE.Get("defaultNamingContext")
	strBase = "<LDAP://" & strDNSDomain & ">"
	strFilter = "(&(objectCategory=person)(objectClass=user)(mail=" &  strMail & "))"
	strAttributes = "displayName,homeMDB"

	strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
	adoCommand.CommandText = strQuery
	adoCommand.Properties("Page Size") = 100
	adoCommand.Properties("Timeout") = 30
	adoCommand.Properties("Cache Results") = False

	Set adoRecordset = adoCommand.Execute
	strDisplayName = adoRecordset.Fields("displayName").Value
	strHomeMDB = adoRecordset.Fields("homeMDB").Value
	adoRecordset.Close
	adoConnection.Close

	Set adoRecordset = Nothing
	Set objRootDSE = Nothing
	Set adoConnection = Nothing
	Set adoCommand = Nothing
End Function

When you have problems/questions please post a reply or give a ‘star’ rating.

Happy scripting.

Best regards,

Dirk Adamsky – Deludi BV

[adrotate group="2"]

Active Directory And WMI: VBscript to monitor all servers in Active Directory

Posted March 4th, 2010 in monitoring, ping by dirk adamsky

The script for today is a monitoring script.
Basically it is a concatenation of previous scripts/functions.
The script can be run as a scheduled task (for example every half hour).

What the script does:

  • run an ado query to get all servers from Active Directory
  • the function CheckStatus does the wmi ping to the servers and returns true or false
  • the servers that do not respond are put into a variable
  • the content of the variable is mailed to a given smtp address

Follow the next steps to run the script (no admin rights needed):

  • copy and paste the script in your favorite text editor
  • save the script (for example c:\tempserveralive.vbs)
  • open a command prompt
  • go to “c:\temp”
  • give “cscript serveralive.vbs” (without quotes) and enter

The script:

' Name : serveralive.vbs
' Description : script to monitor all servers in Active Directory
' Author : dirk adamsky - deludi bv
' Version : 1.10 changed ado filter
' Date : 17-03-2010

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"

' Filter on user objects.
strFilter = "(&(objectCategory=computer)(operatingSystem=*server*))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "name"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
	'On Error Resume Next
	strHostname = adoRecordset.Fields("name").Value
	If CheckStatus(strHostname) = False Then
		strNoReply = strNoReply & " ; " & strHostname
	End If
	'Move to the next record in the recordset.
    adoRecordset.MoveNext
Loop
Sendmail "monitoring@monitoring.org", strNoReply & " are not responding!" 'change the smtp address to your monitoring mailbox or distributionlist
' Clean up.
adoRecordset.Close
adoConnection.Close

Set adoRecordset = Nothing
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing

Function CheckStatus(strAddress)
	Dim objPing, objRetStatus
	Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
      ("select * from Win32_PingStatus where address = '" & strAddress & "'")
	For Each objRetStatus In objPing
        If IsNull(objRetStatus.StatusCode) Or objRetStatus.StatusCode <> 0 Then
			CheckStatus = False
        Else
			CheckStatus = True
        End If
    Next
	Set objPing = Nothing
End Function

Function SendMail(strRecipient, strHeader)
	Set objMessage = CreateObject("CDO.Message")
	objMessage.Subject = strHeader
	objMessage.From = "someone@test.org"
	objMessage.To = strRecipient
	objMessage.TextBody = "This is an automated message do not repond (or else you will be punished)."
	objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
	objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.test.org" 'change to your smtp server
	objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
	objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 60
	objMessage.Configuration.Fields.Update
	objMessage.Send
	Set objMessage = Nothing
End Function

When you have problems/questions please post a reply or give a ‘star’ rating.

Happy scripting.

Best regards,

Dirk Adamsky – Deludi BV

Active Directory: VBscript to enumerate all individual mailbox limits in Active Directory/Exchange

Posted January 27th, 2010 in mailboxlimits by dirk adamsky

This script is intended for reporting purposes.
It enumerates all individual mailbox limits in Active Directory/Exchange.

Follow the next steps to run the script (no admin rights needed):

  • open your favorite text editor
  • copy and paste the script into the editor
  • save the script (for example c:tempmailboxlimits.vbs)
  • open a command prompt
  • go to “c:temp”
  • give “cscript mailboxlimits.vbs” (without quotes) and enter

The script:

' Name : mailboxlimits.vbs
' Description : script  to enumerate all individual mailbox limits in Active Directory/Exchange
' Author : dirk adamsky - deludi bv
' Version : 1.00
' Date : 27-01-2010

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

Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"
strFilter = "(mDBUseDefaults=FALSE)"
strAttributes = "displayname, mail, mDBStorageQuota, mDBOverQuotaLimit, mDBOverHardQuotaLimit, mDBUseDefaults"

strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

Set objRecordset = adoCommand.Execute
Wscript.echo "displayname" & " ; " & "smtp address" & " ; " & "warning limit" &_
 " ; " & "send limit" & " ; " & "send en receive limit"
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
	Wscript.Echo objRecordSet.Fields("displayname").Value & " ; " &_
	objRecordSet.Fields("mail").Value & " ; " &_
	objRecordSet.Fields("mDBStorageQuota").Value/1024 & " MB " &_
	objRecordSet.Fields("mDBOverQuotaLimit").Value/1024 & " MB " &_
	objRecordSet.Fields("mDBOverHardQuotaLimit").Value/1024 & " MB "
	objRecordSet.MoveNext
Loop

Set objRecordset = Nothing
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing