Friday, February 11, 2011

Happy Friday: Scripting Windows Search

As a small example of my previous post, here's a script that reads a search list (text strings, phrases) from a text file, and runs document searches for any that contain those phrases. It involves a few moving parts:
  • A CMD script
  • A VBScript script (sorry, redundant I know)
  • An input text file
  • A "logs" folder beneath the folder that stores the scripts and input file
To test this, drop a bunch of files with matching phrases on your C: drive using various formats like TXT, DOC, DOCX, XLS, XLSX, PPT, PPTX, PDF, CSV, LOG and whatever.  Set up the three files below, then run the scanFiles.cmd script from the computer where the files reside.

CMD script (scanFiles.cmd)

@echo off
SETLOCAL
SET logfile=%~dps0logs\%computername%_files.txt
cscript.exe /nologo "%~dps0scanFiles.vbs" >%logfile%
ENDLOCAL

VBScript (scanFiles.vbs)

'****************************************************************
' Filename..: scanFiles.vbs
' Author....: David M. Stein
' Date......: 02/10/2011
' Purpose...: generate file scan report using Windows Search queries
'****************************************************************
Option Explicit

Const verbose = False

'----------------------------------------------------------------
' comment: DO NOT CHANGE ANY CODE BELOW THIS POINT !!!
'----------------------------------------------------------------

echo "info: script initialized " & Now

Const ForReading = 1
Const ForWriting = 2

Dim objConnection, objRecordset, query, scriptPath, inputFile
Dim objFSO, objFile, strLine, searchList, itemCount : itemCount = 0
Dim filePath, phrase

Set objFSO = CreateObject("Scripting.FileSystemObject")

scriptPath = Replace(wscript.ScriptFullName, "\" & wscript.ScriptName, "")
inputFile = "searchlist.txt"
filePath = scriptPath & "\" & inputFile

On Error Resume Next
echo "info: searching for searchlist.txt input file..."
If objFSO.FileExists(filePath) Then
    echo "info: reading search values..."
    Set objFile = objFSO.OpenTextFile(inputFile, ForReading)
    Do Until objFile.AtEndOfStream
        strLine = objFile.Readline
     If Left(strLine,1) <> ";" Then
         If searchList <> "" Then
             searchList = searchList & vbTab & strLine
         Else
             searchList = strLine
         End If
         itemCount = itemCount + 1
     End If
Loop
    objFile.Close
End If

echo "info: " & itemCount & " phrases were queued"

'----------------------------------------------------------------
  
echo "info: initializing window search interface..."
 
Set objConnection = CreateObject("ADODB.Connection")

echo "info: opening windows search data connection..."
objConnection.Open "Provider=Search.CollatorDSO;Extended " & _
"Properties='Application=Windows';"
If err.Number <> 0 Then
    echo "fail: connection-open failure [" & _
err.Number & ":" & err.Description & "]"
    wscript.quit(2)
End If

echo "info: beginning windows search scan process..."
For each phrase in Split(searchList, vbTab)
    wscript.echo "PHRASE: " & phrase
 
    query = "SELECT System.FileName, System.ItemPathDisplay, " & _
        "System.DateCreated, System.DateModified " & _
     "FROM SYSTEMINDEX WHERE Contains('" & Chr(34) & phrase & Chr(34) & "')"
 Set objRecordSet  = CreateObject("ADODB.Recordset")
objRecordSet.Open query, objConnection
 
    If err.Number <> 0 Then
        echo "fail: recordset-open failure [" & _
         err.Number & ":" & err.Description & "]"
     objConnection.Close
     Set objConnection = Nothing
     wscript.quit(3)
End If

    If Not (objRecordset.BOF and objRecordset.EOF) Then
        objRecordSet.MoveFirst
     echo "info: iterating recordset results..."
     Do Until objRecordset.EOF
         wscript.echo "MATCH: " & _
             objRecordset.Fields.Item("System.ItemPathDisplay").value & _
             vbTab & objRecordset.Fields.Item("System.DateCreated").value & _
             vbTab & objRecordset.Fields.Item("System.DateModified").value
         objRecordset.MoveNext
     Loop
     wscript.echo
Else
        echo "info: no matching records were found"
End If
    objRecordset.Close
    Set objRecordset = Nothing
Next

objConnection.Close
Set objConnection = Nothing

echo "info: processing completed " & Now

Sub Echo(s)
    If verbose = True Then
        wscript.echo s
    End If
End Sub

Input File (searchlist.txt)

; input file, prefix with semi-colon to disable lines
Dogs hate cats
Fish hate cats
Cats love fish

No comments: