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

VBscript: Vbscript to enumerate all accounts with Password Never Expires enabled in Active Directory

Posted May 11th, 2011 in accounts by dirk adamsky

Had some questions on accounts with the “Password Never Expires” setting enabled.

This script enumerates all user accounts in Active Directory en checks if the “Password Never Expires”
marker is set.
The check is no simple 1 or 0 but a bitwise comparison of the userAccountControl Value with
ADS_UF_DONT_EXPIRE_PASSWD (or &H10000 in vbs hex code).
userAccountControl Value for accounts with “Password Never Expires” not enabled -
Decimal: 512 <=> Binary: 1000000000.
ADS_UF_DONT_EXPIRE_PASSWD – Hexadecimal (vbs):  &H10000 <=>
Decimal: 65536 <=> Binary: 10000000000000000.

In the example above the binary comparison gives a zero as result, all non-zero results implicate that the value is enabled.

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:\temp\PasswordNeverExpires.vbs)
* open a command prompt
* go to “c:\temp”
* give “cscript PasswordNeverExpires.vbs” (without quotes) and enter

The script:

' Name : PasswordNeverExpires.vbs
' Description : script to enumerate all accounts with Password Never Expires enabled in Active Directory
' Author : dirk adamsky - deludi bv
' Version : 1.00
' Date : 11-05-2011
' Level: Intermediate

Const ADS_UF_DONT_EXPIRE_PASSWD = &H10000
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("defaultNamingContext") & ">"
strFilter = "(&(objectCategory=person)(objectClass=user))"
strAttributes = "cn,mail,distinguishedName"

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
	On Error Resume Next
	Set objUser = GetObject("LDAP://" & adoRecordset.Fields("distinguishedName").Value)
	If (objUser.userAccountControl And ADS_UF_DONT_EXPIRE_PASSWD) <> 0 Then
		Wscript.echo adoRecordset.Fields("cn").Value & " ; " & adoRecordset.Fields("mail").Value
	End If
	Set objUser = Nothing
    adoRecordset.MoveNext
Loop

adoRecordset.Close
adoConnection.Close

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

When you have problems/questions with the script please post a reply.

Happy scripting.

Best regards,

Dirk Adamsky

Active Directory: VBscript to enumerate all contacts in your domain

Posted January 14th, 2011 in contacts by dirk adamsky

This is my first post for 2011.

Last week I had to do some work on Active Directory contacts.
For a starter I made a script that enumerates all contacts in Active Directory.
Be careful: this script does not include your local contact (they are a part of your mailbox).
The script is straight ahead: ADO query, filter on ‘objectclass=contacts’ and off you go.

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:tempenumeratecontacts.vbs)
* open a command prompt
* go to “c:temp”
* give “cscript enumeratecontacts.vbs” (without quotes) and enter

The script:

' Name : enumeratecontacts.vbs
' Description : script to enumerate all contacts in your domain
' Author : dirk adamsky - deludi bv
' Version : 1.00
' Date : 14-01-2011
' Level: beginner

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 = "(objectClass=contact)"
strAttributes = "displayname, mail"
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
 Wscript.echo adoRecordset.Fields("displayname").Value & " ; " & adoRecordset.Fields("mail").Value
 adoRecordset.MoveNext
Loop

adoRecordset.Close
adoConnection.Close

Set adoConnection = Nothing
Set adoCommand = Nothing

When you have problems/questions with the script please post a reply.

Happy scripting.

Best regards,

Dirk Adamsky

Active Directory and WMI: VBscript to enumerate the system uptime of all servers in Active Directory V2

Posted July 15th, 2010 in active directory, uptime, vbscript, wmi by dirk adamsky

The script for today is created for Paul.
It is an extension of the previous server uptime script.
The uptime is now formatted in: xx days, xx hours, xx minutes.


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

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

The script:

' Name : serveruptimev2.vbs
' Description : script to enumerate the system uptime of all servers in Active Directory V2
' Author : dirk adamsky - deludi bv
' Version : 2.00
' Date : 15-07-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 = "(&(objectCategory=computer)(operatingSystem=*server*))"
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
	On Error Resume Next
	strHostname = adoRecordset.Fields("name").Value
	If CheckStatus(strHostname) = False Then
		Wscript.Echo strHostname & " does not reply"
	Else
		Wscript.Echo strHostname & " is up for " & GetUptime(strHostname)
	End If
	adoRecordset.MoveNext
Loop

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 GetUptime(strServer)
	Set objDateTime = CreateObject("WbemScripting.SWbemDateTime")
	Set objWMIService = GetObject("winmgmts:\" & strServer & "rootcimv2")
	Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
	For Each objOS in colOperatingSystems
		objDateTime.Value = objOS.LastBootUpTime
		strMinutes = DateDiff("n", objDateTime.GetVarDate, Now)
		If strMinutes =< 0 Then
			strUptime = "0 days, 0 hours, 0 minutes"
		Else
			strUptime = ""
			If strMinutes >= 1440 Then
				strUptime = Round(strMinutes1440,0) & " days,"
			End If
			strMinutes = strMinutes Mod 1440
			If strMinutes >= 60 Then
				strUptime = strUptime & (strMinutes60) & " hours,"
			End If
			strMinutes = strMinutes Mod 60
			GetUptime = strUptime & strMinutes & " minutes"
		End If
	Next
	Set colOperatingSystems = Nothing
	Set objWMIService = Nothing
	Set objDateTime = 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" banner="3"]