Tips
Inventorying Virtual Hard Disk Files on a Server or Domain
Use these scripts to list the VHD or VMDK files on any system
Chris: I'm starting to get worried about VM sprawl. Many of the
users on my network are using Virtual PC and Virtual Server 2005 R2, and I want
to be able to find VHD files on my servers or on any user's system. Can I do
this with a tool or script?
--
Jason
Jason, while many enterprise storage resource management (SRM) tools can audit
files by extension, this can also be done using a vbscript. For example, the
script below will show you all Virtual PC or Virtual Server (VHD) and VMware
(VMDK) virtual hard disk files. Also, the script will display any files greater
than 800MB (838,860,800 bytes), which is useful for the crafty user that decides
to create virtual disk files using a custom file extension.
'vhdaudit.vbs
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\"
& _
strComputer & "\root\cimv2")
Set colFiles = objWMIService. _
ExecQuery("Select * from CIM_DataFile "
& _
"where Extension = 'vhd' or Extension ="
& _
" 'vmdk' or FileSize > 838860800")
For Each objFile in colFiles
Wscript.Echo objFile.Name & " -- " &
_
objFile.FileSize & " bytes"
Next
Note that if you wanted to list all files greater than 100MB in size, for example,
you would change "838860800" in the "Set colFiles" statement
to "104857600." There are plenty of online calculators that can convert
megabytes to bytes, so if you're looking to audit a particular file size, you
can use this Conversion
Calculator, for example.
I have saved a copy of vhdaudit.vbs on my Web site and you can download it
here.
Note that it is saved as a text file, so you will need to change its extension
to .vbs in order to run it. Also, since the script uses wscript.echo to list
the virtual hard disk files that are found, you should run it using the cscripting
host. To do this, you would run the command cscript vhdaudit.vbs
from the directory containing the vhdaudit.vbs file.
If you would like to find virtual hard disk files on every computer in your
domain, you can run the DomainVHDaudit.vbs
script shown below.
'DomainVHDaudit.vbs
On Error Resume Next
Const ForWriting = 2
' Format date/time stamp for output file
strTimeDate = Year(Date) & "-" & Month(Date) & _
"-" & Day(Date) & "~~" & Hour(Time)
& "-" & _
Minute(Time)
' Output file name and path
strLogFile = "C:\VHDaudit-" & strTimeDate & _
".txt"
wscript.echo("Audit started. This may take " &
_
"several minutes to hours to complete. You " & _
"will receive a message once the script is finished.")
'Create Log File
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile (strLogFile, _
ForWriting, True)
' Connect to domain and collect computer accounts
Const ADS_SCOPE_SUBTREE = 2
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
set objRootDSE = GetObject("LDAP://RootDSE")
objCommand.CommandText = _
"SELECT Name, Location FROM 'LDAP://" & _
objRootDSE.Get("defaultNamingContext") & "'"
_
& "WHERE objectClass='computer'"
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Timeout") = 30
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
' Output domain computer accounts, connect to each
' computer, and enumerate virtual disk files or
' files larger than 800 MB
Do Until objRecordSet.EOF
strComputer = objRecordSet.Fields("Name").Value
objFile.WriteLine "System: " & strComputer
Set objWMIsvc = GetObject("winmgmts:" &_
"{impersonationlevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
'Check for connection error. If systems are
'unreachable, ensure that a software firewall
'is not blocking WMI connections.
If Err = 462 Then
objFile.Writeline("*** System Unreachable ***")
Err.Clear
Else
'Enumerate VHDs and VMDKs
set colFiles = objWMIsvc.ExecQuery _
("Select * from CIM_DataFile where Extension
=" & _
" 'vhd' or Extension = 'vmdk' or FileSize "
& _
"> 838860800")
' Note: 838860800 is the byte value of 800 MB
'List VHDs on host
For Each objVHD In colFiles
objFile.WriteLine(objVHD.Name & " --
" & _
objVHD.FileSize & " bytes")
Next
End If
objfile.writeline("-------------------------------")
objfile.writeline()
objRecordSet.MoveNext
Loop
' All done!
WScript.Echo("Audit Complete!")
Note that the file audit may take up to several minutes to complete per computer.
So running this script in a domain with hundreds to thousands of computers can
conceivably take hours. The script will write its output to a text file on the
C drive on the computer in which it is run. Note that the script uses the naming
convention "VHDaudit-year-month-day~~time.txt" for its output file.
The script works by querying Active Directory to collect all computer and domain
controller objects. It will then connect to each object and look for VHD, VMDK
or files larger than the size specified in the "FileSize" parameter.
The complete audit will be written to a single text file and computers that
cannot be contacted will be noted in the text file with a "*** System Unreachable
***" message. Computers that cannot be reached are likely those that are
not connected to the LAN or have their software firewall set to refuse WMI queries.
Hopefully, one of these two scripts will help solve your problem. The vhdaudit.vbs
script is ideal for performing local audits on each of your file servers. To
audit your entire domain, domainvhdaudit.vbs should "git 'r done."