Friday, May 20, 2011

VBScript: MD5 sum and file details into CSV

Some things are trivial in Linux/Unix and more complex in Windows. In Linux, it's md5sum filename. In Windows, there are free tools from Microsoft (fciv.exe), but no built-in commands that are super-easy to script.

So what are you to do if you need to collect file details and hashes for every folder within the subfolders of a directory? If you're doing it with VBScript, you'll need a free library available from XStandard. Once you register, you'll get a dll that you'll need to register. (It's 32-bit only, so if you're on a 64-bit box, you'll need to do this:
C:\WINDOWS\SysWOW64\regsvr32.exe XMD5.dll
and then to execute the script:
c:\windows\SysWOW64\cscript.exe FolderReportMD5.vbs )

Anyhow, this script is derived from the Sapien sample scripts. (While there are many free editors out there, I think Sapien's PrimalScript is worth every penny if you'll be doing a lot of Windows scripting.)

And since my MT template doesn't handle code well, here's a link to the text file.

'**************************************************************************
' File: FileListMD5.vbs
'
' Comments: This script uses the MD5 library available here:
' http://www.xstandard.com/en/documentation/xmd5/#api1
' This script runs through a directory tree and writes file attributes to a csv file.
' To run on x64 use C:\WINDOWS\SysWOW64\regsvr32.exe XMD5.dll and then execute via
' c:\windows\SysWOW64\cscript.exe FolderReportMD5.vbs
' Based on Sapien's sample script for FolderProperties.
'**************************************************************************
Set objFSO2 = createobject("scripting.filesystemobject")
'where to put the file list?
Set objFile = objFSO2.createtextfile("c:\scripts\" & "FileList" & ".csv")
q = """"
'write the header line of the CSV file.
objFile.WriteLine(q & "FilePath" & q & "," & q & "FileName" & q & "," & q & "DateCreated" & q _
& "," & q & "DateLastAccessed" & q & "," & q & "DateLastModified" & q & "," & q & "FileSize" & q &_
"," & q & "MD5Hash" & q & "," & q & "FileAttributes" & q)

'where to start
strSource="C:\folder"

Set objFSO=CreateObject("Scripting.FileSystemObject")
Set objFolder=objFSO.GetFolder(strSource)

Call ProcessFiles(objFolder)

Sub ProcessFiles(objFolder)
Set colFiles=objFolder.Files


For Each file In colFiles
'it's a good idea to clear out the vars on each loop
strFingerPrint = "blank"
strPath = File.Path
Set objMD5 = CreateObject("XStandard.MD5")
strFingerPrint = objMD5.GetCheckSumFromFile(strPath)
Set objMD5 = Nothing
wscript.Echo strFingerPrint
wscript.Echo "File Name:" & vbTab & File.Name
wscript.Echo "Short File Name:" & vbtab & File.ShortName
wscript.Echo "File Path:" & vbtab & File.Path
wscript.Echo "Date Created:" & vbtab & File.DateCreated
wscript.Echo "Date Last Accessed:" & vbtab & File.DateLastAccessed
wscript.Echo "Date Last Modified:" & vbtab & File.DateLastModified
wscript.Echo "File Size:" & vbtab & File.Size
wscript.Echo "File Attributes:"
strFileAttributes = " "
if File.Attributes AND 0 Then wscript.Echo " Normal"
If File.Attributes And 0 Then strFileAttributes = strFileAttributes & " Normal"
if File.Attributes AND 1 then wscript.Echo " Read-only"
If File.Attributes And 1 Then strFileAttributes = strFileAttributes & " Read-only"
if File.Attributes AND 2 then wscript.Echo " Hidden"
If File.Attributes And 2 Then strFileAttributes = strFileAttributes & " Hidden"
if File.Attributes AND 4 then wscript.Echo " System"
If File.Attributes And 4 Then strFileAttributes = strFileAttributes & " System"
if File.Attributes And 8 Then wscript.Echo " Volume"
If File.Attributes And 8 Then strFileAttributes = strFileAttributes & " Volume"
if File.Attributes AND 16 then wscript.Echo " Directory"
If File.Attributes And 16 Then strFileAttributes = strFileAttributes & " Directory"
if File.Attributes And 32 Then wscript.Echo " Archive Bit is set"
If File.Attributes And 32 Then strFileAttributes = strFileAttributes & " Archive Bit is set"
If File.Attributes AND 1024 then wscript.Echo " Alias"
If File.Attributes And 1024 Then strFileAttributes = strFileAttributes & " Alias"
if File.Attributes AND 2048 then wscript.Echo " Compressed"
If File.Attributes And 2048 Then strFileAttributes = strFileAttributes & " Compressed"

'finally, write the line to the csv file
objFile.WriteLine(q & File.Path & _
q & "," & q & File.Name & q & "," & _
q & File.DateCreated & q & "," & q & File.DateLastAccessed & q & "," & q _
& File.DateLastModified & q & "," & q & File.Size & q & "," & q & strFingerPrint & q & "," & q & strFileAttributes & q)

Next
'process Subfolders
Call ProcessSubFolders(objFolder)

End Sub

Sub ProcessSubFolders(objFolder)
Set colSubs=objFolder.SubFolders
For Each folder In colSubs
ProcessFiles(folder)
Next

End Sub