It was pointed out to me, by a party that shall remain nameless, that I depended in today's earlier post Finding Disk Space Used By Exchange Version 2, that I ASSumed that msExchCurrentServerRoles would never be higher than 64 and that that was a bad assumption on my part, for reasons that shall also remain nameless.
So, here is a "fixed" version of just the ShowServerInfo() subroutine. Just rip the old one out, and add the new one in:
Const Exch_Role_Edge = 64 ' 0x40
Const Exch_Role_Hub = 32 ' 0x20
Const Exch_Role_UM = 16 ' 0x10
Const Exch_Role_ClientAccess = 4 ' 0x04
Const Exch_Role_Mailbox = 2 ' 0x02
Sub ShowServerInfo (ByVal spaces, ByVal strServer)
Dim objServer, obj
Dim str, i, msExchCurrentRoles
On Error Resume Next
Err.Clear
Set objServer = GetObject ("LDAP://" & strServer)
If Err = 0 Then
msExchCurrentRoles = objServer.Get ("msExchCurrentServerRoles")
If Err = 0 Then
i = msExchCurrentRoles
str = ""
'' got a exchange 2007 or higher box
If (msExchCurrentRoles and Exch_Role_Mailbox) = Exch_Role_Mailbox Then
str = str & "Mailbox "
i = i - Exch_Role_Mailbox
End If
If (msExchCurrentRoles and Exch_Role_ClientAccess) = Exch_Role_ClientAccess Then
str = str & "ClientAccess "
i = i - Exch_Role_ClientAccess
End If
If (msExchCurrentRoles and Exch_Role_UM) = Exch_Role_UM Then
str = str & "UnifiedMessaging "
i = i - Exch_Role_UM
End If
If (msExchCurrentRoles and Exch_Role_Hub) = Exch_Role_Hub Then
str = str & "HubTransport "
i = i - Exch_Role_Hub
End If
If (msExchCurrentRoles and Exch_Role_Edge) = Exch_Role_Edge Then
str = str & "EdgeTransport "
i = i - Exch_Role_Edge
End If
If i <> 0 Then
str = str & vbCRLF & Space (spaces) & _
"Unknown bits set in msExchCurrentRoles = 0x" & Hex(i)
End If
e Space (spaces) & "Exchange roles installed: " & str
Else
i = objServer.Get ("serverRole")
If i = 1 Then
e Space (spaces) & "Exchange role: Front-end server"
Else
e Space (spaces) & "Exchange role: Back-end server"
End If
End If
Err.Clear
obj = objServer.Get ("serialNumber")
If Err = 0 Then
If IsNull (obj) Then
e Space (spaces) & "No version found"
ElseIf IsEmpty (obj) Then
e Space (spaces) & "Version string is empty"
ElseIf IsArray (obj) Then
For Each str in obj
e Space (spaces) & str
Next
Else
e Space (spaces) & obj
End If
End If
Err.Clear
End If
e " "
Set objServer = Nothing
On Error Goto 0
End Sub
Until next time...
As always, if there are items you would like me to talk about, please drop me a line and let me know!
In July of 2006, I had a blog entry named Finding Disk Space Used By Exchange, and it was quite well received and it worked well for most people.
However, it had a few issues:
-
It doesn't work with Exchange Server 2007 because the streaming file was removed from Exchange
-
If a Recovery Storage Group was present, but the files were removed, it would fail
-
If an Exchange Server was not reachable via UNC path, it would fail
There was also one out-and-out bug: Per-server totals were not zeroed after each server was evaluated.
And from a feature perspective, lots of folks wanted some information about the storage groups (circular logging, log prefix, etc.) and the servers (version and server roles).
There is a Microsoft script that also contains much of this information, but it is based on CDOEXM, which means that it pretty much must run on an Exchange 2003 server; and it also has the same three issues mentioned above (plus a couple of others - for example, if the EDB and STM files were separated on different volumes or path, it would also fail). James Chong, another Microsoft Exchange MVP, pointed out that script to me. It does have a feature of reporting the current sizes of the logs being used by a storage group.
So, in this version 2, I've fixed the three issues above, fixed the out-and-out bug, and now I provide a fair bit of information about each storage group. I think I also now check for all possible errors that could occur. As before, this script does depend on my Utility Libraries for Exchange Scripting.
I have tested this script in an environment containing Exchange 2000, Exchange 2003, and Exchange 2007. It should work for you with all of those too!
Some sample output from my small test environment:
Exchange Organization Name: First Organization
Default SMTP address for organization: essential.local
All Exchange Servers in forest DC=essential,DC=local
Server Name: WIN2003-EXCH
Server Name: WIN2008-EXCH
Server name: WIN2003-EXCH
Exchange role: Back-end server
Version Version 6.5 (Build 7638.2: Service Pack 2)
Storage group: First Storage Group
Circular Logging is False
Zero out deleted databse pages is False
Log file prefix is E00
Transaction log location is C:\Program Files\Exchsrvr\mdbdata
System path location is C:\Program Files\Exchsrvr\mdbdata
Store: Public Folder Store (WIN2003-EXCH)
EDB file: C:\Program Files\Exchsrvr\mdbdata\pub1.edb
Size: 18 megabytes
SLV file: C:\Program Files\Exchsrvr\mdbdata\pub1.stm
Size: 4 megabytes
Store Size Total: 22 megabytes
Store: Mailbox Store (WIN2003-EXCH)
EDB file: C:\Program Files\Exchsrvr\mdbdata\priv1.edb
Size: 6 megabytes
SLV file: C:\Program Files\Exchsrvr\mdbdata\priv1.stm
Size: 8 megabytes
Store Size Total: 14 megabytes
Storage Group total: 36 megabytes
Server total: 36 megabytes
Server name: WIN2008-EXCH
Exchange roles installed: HubTransport ClientAccess Mailbox
Version Version 8.1 (Build 30240.6)
Storage group: First Storage Group
Circular Logging is False
Zero out deleted databse pages is False
Log file prefix is E00
Transaction log location is C:\Program Files\Microsoft\Exchange Server\Mailbox\First Storage Group
System path location is C:\Program Files\Microsoft\Exchange Server\Mailbox\First Storage Group
Store: Mailbox Database
EDB file: C:\Program Files\Microsoft\Exchange Server\Mailbox\First Storage Group\Mailbox Database.edb
** Could not open file: \\WIN2008-EXCH\C$\Program Files\Microsoft\Exchange Server\Mailbox\First Storage Group\Mailbox Database.edb
Could not find streaming filename in active directory
Store Size Total: 0 megabytes
Storage Group total: 0 megabytes
Storage group: Recovery Storage Group
Circular Logging is False
Zero out deleted databse pages is False
Log file prefix is R00
Transaction log location is C:\rsg
System path location is C:\rsg
Store: Mailbox Database
EDB file: C:\rsg\Mailbox Database.edb
** Could not open file: \\WIN2008-EXCH\C$\rsg\Mailbox Database.edb
Could not find streaming filename in active directory
Store Size Total: 0 megabytes
Storage Group total: 0 megabytes
Storage group: Second Storage Group
Circular Logging is False
Zero out deleted databse pages is False
Log file prefix is E01
Transaction log location is C:\Program Files\Microsoft\Exchange Server\Mailbox\Second Storage Group
System path location is C:\Program Files\Microsoft\Exchange Server\Mailbox\Second Storage Group
Store: Public Folder Database
EDB file: C:\Program Files\Microsoft\Exchange Server\Mailbox\Second Storage Group\Public Folder Database.edb
** Could not open file: \\WIN2008-EXCH\C$\Program Files\Microsoft\Exchange Server\Mailbox\Second Storage Group\Public Folder Database.edb
Could not find streaming filename in active directory
Store Size Total: 0 megabytes
Storage Group total: 0 megabytes
Server total: 0 megabytes
Organization total: 36 megabytes
And here is the code for your enjoyment:
<JOB>
<SCRIPT language="VBScript">
Option Explicit
</SCRIPT>
<SCRIPT language="VBScript" src="lib/constants.vbs" mce_src="lib/constants.vbs">
<script language="VBScript" src="lib/ado.vbs" mce_src="lib/ado.vbs" >
<script language="VBScript" src="lib/report.vbs" mce_src="lib/report.vbs" >
<script language="VBScript" src="lib/systeminfo.vbs" mce_src="lib/systeminfo.vbs" >
<script language="VBScript" src="lib/queries.vbs" mce_src="lib/queries.vbs" >
<script language="VBScript">
'
' exch-store-space.wsf
'
' This program reports on the space utilization of the EDB and STM
' files for all stores for all storage groups for all servers in the
' Exchange organization.
'
' Updated on August 8, 2008 to deal with missing files
' Also now works with Exchange 2007 (no msExchSLVFile attribute on 2007 servers)
' Also dumps some data about each individual storage group
' Also won't abort on missing Recovery Storage Group
' Also total per-server correctly
'
Dim arr, arrSG, arrStore
Dim s, s1, strServer
Dim i, j, k, orgTotal
Dim objFSO
Call GetSystemInfo
Call GetAllServers
Set objFSO = CreateObject ("Scripting.FileSystemObject")
arr = Split (strServerListDN, ";")
For i = LBound (arr) To UBound (arr)
Dim serverTotal
serverTotal = 0
s = arr (i)
strServer = Mid (Left (s, Instr (s, ",") - 1), 4)
e "Server name: " & strServer
Call ShowServerInfo (2, s)
Call GetStorageGroupsForServer (arr (i))
arrSG = Split (strServerSGDN, ";")
For j = LBound (arrSG) To UBound (arrSG)
Dim sgTotal
sgTotal = 0
s = arrSG (j)
s1 = Mid (Left (s, Instr (s, ",") - 1), 4)
e Space (2) & "Storage group: " & s1
Call ShowStorageGroupInfo (4, s)
Call GetStoresForStorageGroupLDAP (s)
arrStore = Split (strStoreDN, ";")
For k = LBound (arrStore) To UBound (arrStore)
Dim obj, objFile, strFile, storeTotal
storeTotal = 0
s = arrStore (k)
s1 = Mid (Left (s, Instr (s, ",") - 1), 4)
e Space (4) & "Store: " & s1
On Error Resume Next
Err.Clear
Set obj = GetObject ("LDAP://" & s)
If Err Then
e Space (6) & "** Could not open store in active directory"
Else
s = obj.Get ("msExchEDBFile")
If Err Then
e Space (6) & "** Could not find EDB filename in active directory"
Else
e Space (6) & "EDB file: " & s
' must convert the file to a UNC path
strFile = "\\" & strServer & "\" & _
Left (s, 1) & "$" & Mid (s, 3)
Set objFile = objFSO.GetFile (strFile)
If Err Then
e Space (6) & "** Could not open file: " & strFile
Else
e Space (6) & "Size: " & _
FormatNumber (objFile.Size / (1024 * 1024), 0) & _
" megabytes"
storeTotal = storeTotal + (objFile.Size / (1024 * 1024))
End If
End If
Err.Clear
s = obj.Get ("msExchSLVFile")
If Err Then
e Space (6) & "Could not find streaming filename in active directory"
Else
e Space (6) & "SLV file: " & s
strFile = "\\" & strServer & "\" & _
Left (s, 1) & "$" & Mid (s, 3)
Set objFile = objFSO.GetFile (strFile)
If Err Then
e Space (6) & "** Could not open file: " & strFile
Else
e Space (6) & "Size: " & _
FormatNumber (objFile.Size / (1024 * 1024), 0) & _
" megabytes"
storeTotal = storeTotal + (objFile.Size / (1024 * 1024))
End If
End If
Err.Clear
e Space (6) & "Store Size Total: " & _
FormatNumber (storeTotal, 0) & _
" megabytes"
sgTotal = sgTotal + storeTotal
End If
On Error Goto 0
Next
e Space (4) & "Storage Group total: " & FormatNumber (sgTotal, 0) & _
" megabytes"
serverTotal = serverTotal + sgTotal
Next
e Space (2) & "Server total: " & FormatNumber (serverTotal, 0) & " megabytes"
e " "
orgTotal = orgTotal + serverTotal
Next
e "Organization total: " & FormatNumber (orgTotal, 0) & " megabytes"
Call ClearSystemInfo
Sub ShowServerInfo (ByVal spaces, ByVal strServer)
Dim objServer, obj
Dim str, i
On Error Resume Next
Err.Clear
Set objServer = GetObject ("LDAP://" & strServer)
If Err = 0 Then
i = objServer.Get ("msExchCurrentServerRoles")
If Err = 0 Then
str = ""
'' got a exchange 2007 or higher box
If i >= 64 Then
str = str & "EdgeTransport "
i = i - 64
End If
If i >= 32 Then
str = str & "HubTransport "
i = i - 32
End If
If i >= 16 Then
str = str & "UnifiedMessaging "
i = i - 16
End If
If i >= 4 Then
str = str & "ClientAccess "
i = i - 4
End If
If i >= 2 Then
str = str & "Mailbox"
i = i - 2
End If
e Space (spaces) & "Exchange roles installed: " & str
Else
i = objServer.Get ("serverRole")
If i = 1 Then
e Space (spaces) & "Exchange role: Front-end server"
Else
e Space (spaces) & "Exchange role: Back-end server"
End If
End If
Err.Clear
obj = objServer.Get ("serialNumber")
If Err = 0 Then
If IsNull (obj) Then
e Space (spaces) & "No version found"
ElseIf IsEmpty (obj) Then
e Space (spaces) & "Version string is empty"
ElseIf IsArray (obj) Then
For Each str in obj
e Space (spaces) & "Version " & str
Next
Else
e Space (spaces) & "Version " & obj
End If
End If
Err.Clear
End If
e " "
Set objServer = Nothing
On Error Goto 0
End Sub
Sub ShowStorageGroupInfo (ByVal spaces, ByVal strSG)
Dim objSG
Dim str, i
Dim prefix
prefix = "msExchESEParam" '' all storage group attributes start with that prefix
On Error Resume Next
Err.Clear
Set objSG = GetObject ("LDAP://" & strSG)
If Err = 0 Then
i = objSG.Get (prefix & "CircularLog")
If Err = 0 Then
e Space (spaces) & "Circular Logging is " & CBool(i)
End If
Err.Clear
i = objSG.Get (prefix & "ZeroDatabaseDuringBackup")
If Err = 0 Then
e Space (spaces) & "Zero out deleted databse pages is " & CBool (i)
End If
Err.Clear
str = objSG.Get (prefix & "BaseName")
If Err = 0 Then
e Space (spaces) & "Log file prefix is " & str
End If
Err.Clear
str = objSG.Get (prefix & "LogFilePath")
If Err = 0 Then
e Space (spaces) & "Transaction log location is " & str
End If
Err.Clear
str = objSG.Get (prefix & "SystemPath")
If Err = 0 Then
e Space (spaces) & "System path location is " & str
End If
Err.Clear
e " "
Else
e Space (spaces) & "** Couldn't open " & strSG
End If
Set objSG = Nothing
On Error Goto 0
End Sub
</SCRIPT>
</JOB>
Until next time...
As always, if there are items you would like me to talk about, please drop me a line and let me know!