Alright, I haven’t posted in a while, but I also haven’t had any new issues develop that I felt would be helpful or insightful to any of you out there. But today, I did have to write a script to find out if a file had been copied from the directory it was supposed to be in to any other place in the domain. At first, I thought they were crazy, but I turned to my good friend VBScript and got the job done. There are several pieces to this script, each very useful in it’s own right. First, it connects to the domain controller and finds out what domain you are in(handy if you work on several domains and don’t want to fiddle to make it work different places), then it makes a .txt file with every computer account in the domain on a line. The next step is pinging each of the machines listed to see if they are are available. Then, it connects and scans the C drive (via c$) for the file name recursively scans hidden folders and files as well. Then, it finds any shared folders on the system(say a server, where shares are not on C:) and scans them recursively. It reports if the file was found on the system or not and if it was, the exact location on the machine. Anyway, let me know if you have any questions on how to get this working for different scenarios or need to just make certain snippets work.
***Updated 8/7/09 with revisions to make script shorter, more efficient and work better with regular expression/pattern searching***
''Script to find all machines in AD, search C drive of all machines for a pattern in the filename, then search any shared folders for the file and reports
'' whether it was found and whether the machines are reachable by ping.
'' Side Note -- Can not scan shares on Windows 2000 or older, it will simply skip those shares. It will still scan C drive on Windows 2000, not NT
Option Explicit
CONST HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim strResultsFile, strServerName, strErrorNumber, strErrorDescription
Dim strAge, strLatestFile, strClientName, strDNSDomain
Dim strBase, strFilter, strAttributes, strQuery
Dim objWMIService, objLocator, objResultsFile, objRootDSE, objCommand, objConnection
Dim objRecordSet
Dim strSearchName
Dim objNetwork : Set objNetwork = CreateObject("WScript.Network")
Dim strFileName : strFileName = "computers.txt"
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim WshShell : Set WshShell = CreateObject("wscript.shell")
Dim i
Dim ii
Dim objFile, objCurrentFile, objTempList, objFS, objList, strCurrentFile2, objLogFile1, objLogFile2
Dim strComputer()
Dim strRet
'Here, you can put in the Regulare Expression pattern to use when searching.
Dim objRegEx : Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Global = True
objRegEx.IgnoreCase = True
objRegEx.Pattern = ".*pip_dvalles.*"
Dim IsFound
Dim strReply, png, strPing
Dim strList, objShare, strShare
Dim strShares()
Dim strDate, strTime, strHour, strMinute, strSeconds, Now, NowStart, ConnectTime
NowStart = Now
strResultsFile = "computers.txt"
strDate = CStr(Year(Date) * 10000 + Month(Date) * 100 + Day(Date))
strTime = Time
strHour = Hour (strTime)
strMinute = Minute (strTime)
strSeconds = Second (strTime)
Dim strFound, strNotFound
strFound = "C:\Found.txt"
strNotFound = "C:\NotFound.txt"
Set objLogFile1 = objFSO.OpenTextFile(strNotFound, ForAppending, True)
Set objLogFile2 = objFSO.OpenTextFile(strFound, ForAppending, True)
'Check for the presence of the Computer.txt file in the same folder as the script
If Not objFSO.FileExists(strFileName) Then
Set objResultsFile = objFsO.OpenTextFile (strResultsFile, ForWriting, True)
' Start getting a list of all servers from AD
' Determine DNS domain name from RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
'Start the ADO connection
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection
'Set the ADO connection query strings
strBase = ""
strFilter = "(objectCategory=computer)"
strAttributes = "distinguishedName,objectCategory,name"
'Create the Query
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
'Find all computers in the domain
While Not objRecordset.EOF
ON ERROR RESUME NEXT
strServerName = objRecordset.Fields("name")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strServerName & "\root\cimv2")
strErrorNumber = Err.Number
strErrorDescription = Err.Description
objResultsFile.WriteLine strServerName
'NEXT!
objRecordSet.MoveNext
Wend
objResultsFile.Close
WScript.Echo "All computer accounts in " & strDNSDOMAIN & " have been found." & vbCrLf & "Click OK to scan for file: " & objSearchFile
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
Else
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
End if
'start parsing through computer.txt
Do Until objFile.AtEndOfStream
isFound = FALSE
Redim Preserve strComputer(i)
strComputer(i) = objFile.ReadLine
'Ping Computers to make sure that they are reachable.
Set png = WshShell.exec("ping -n 1 " & strComputer(i))
Do Until png.Status = 1 : WScript.Sleep 10 : Loop
strPing = png.StdOut.ReadAll
'NOTE: The string being looked for in the Instr is case sensitive.
'Do not change the case of any character which appears on the
'same line as a Case InStr. AS this will result in a failure.
Select Case True
Case InStr(strPing, "Request timed out") > 1
strReply = "Request timed out"
Case InStr(strPing, "could not find host") > 1
strReply = "Host not reachable"
Case InStr(strPing, "Reply from") > 1
strReply = "Ping Successful"
End Select
' Connects to the operating system's file system
ON ERROR RESUME NEXT
Set objFS = GetObject("WinNT://" & strComputer(i) & "/LanmanServer,FileService")
objList = ""
' Loops through each share and checks for file
For Each objShare In objFS
strShare = LCase(objShare.name)
Set objTempList = WshShell.Exec("cmd /c dir /a/s/b \\" & strComputer(i) & "\" & strShare)
Do Until objTempList.StdOut.AtEndOfStream
objCurrentFile = objTempList.StdOut.ReadLine
If objRegEx.Test(objFSO.GetBaseName(objCurrentFile)) Then
strCurrentFile2 = objfSO.GetBaseName(objCurrentFile)
objLogFile2.WriteLine Now & " - The file " & objSearchFile & " was found on " & strComputer(i) & " at " & objCurrentFile
isFound = True
Else
If isFound = False Then
isFound = False
Else
isFound = True
End If
End If
Loop
objList = LCase(objShare.name) & vbCrLf & objList
Next
'Check for file on remote PC
Set objTempList = WshShell.Exec("cmd /c dir /a/s/b \\" & strComputer(i) & "c$")
Do Until objTempList.StdOut.AtEndOfStream
objCurrentFile = objTempList.StdOut.ReadLine
If objRegEx.Test(objFSO.GetBaseName(objCurrentFile)) Then
strCurrentFile2 = objfSO.GetBaseName(objCurrentFile)
objLogFile2.WriteLine Now & " - The file " & objSearchFile & " was found on " & strComputer(i) & " at " & objCurrentFile
isFound = True
Else
If isFound = False Then
isFound = False
Else
isFound = True
End If
End If
Loop
'Write to Not Found Log, if not found.
If isFound = False Then
objLogFile1.WriteLine Now & "No File matching the pattern (" & objRegEx.Pattern & ") was found on " & strComputer(i)
End If
Loop
objLogFile1.Close
objLogFile2.Close
WScript.Echo "Done scanning, LogFiles are located at:" & vbCrLf & strFound & vbCrLf & strNotFound & vbCrLf & "Click OK to finish"
Hope this helps someone out there.
« System Administrator Appreciation Day! Project Euler – Problems 1 & 2 »


Sweet, I def fills a need for me. I cannot get it to populate the computer list. If i hard code the computer name the and change the “.*pip_dvalles.*” to “notepad.*” it doesn’t find it.
sweet! couldn’t come at a better time.. i’m skimming the code and looks like you’re outputting the results on each c drive of each machine.. don’t know how complicated it would be, but it’d be nicer if we could output the results in 1 file saved on the share somewhere. that way we have 1 location to see the results instead of having to dig through each computer. and all you simply have is the computer name & result (i.e. found: location, not found, can’t ping, or other error)
ah. ok. you make it so simple.. no.. that’s kind of what i need at the moment. I’m sure I can always modify if I need extra stuff. thanks
This post was mentioned on Twitter by Richard Hawkesford.
This is what I have been searching for. I am a noob so I will need some help tailoring this. Basically I am looking for a code that will search the computers hard drive for a file called isr.xls. The computers have user profiles (don’t know if that matters). I then need to import that file into my access database and add an autonumber column to the file. Is this do-able?
so once the isr.xls file is found(i assume one on each machine from your comment), you want to import each one into the access db and number based on computername or just numbered in order found? It’s doable, I can try some things out, but am a little short on time right now. I can take a look this weekend, but if you want some input sooner, I would take this script and run over to http://www.visualbasicscript.com; those guys are really helpful.
I am trying to make this work. The script runs in about 10 sec and says its done. nothing in txt files. I am searching for .pst and .ost files through out the domain.
I would ideally like to have it all in one csv file. For now I am not able to get this working at all. I am not an expert and not a newby at VB. Can you make more detailed comments so I can understand just a bit more?
Thanks
Can you tell if the computers.txt files is populating, or did you manually create it beforehand? does it pop up other cmd screens, or just do nothing altogether. Also, what does your RegEx look like? Should be “*.pst” and “*.ost”. I’m not sure what is going wrong when you run it, but if we start with verifying that there is something in the computers.txt file, then we can go from there.
Couple things, first, make sure you don’t open the computers.txt whil the program is running, it will stop populating. Also, does it give any errors? and does it start popping up cmd screens real quick(this is what it does the second half of script when pinging to see if the machine is alive)? the “.*” together mean 0 or more of any character. “.” means 1 of any character/letter/number, and “*” means 0 or more(infinitely) of the previous character. so this means that unless the file starts with notepad, it wont find it. Also, note (this was simply my stupidity) that there are 2 variables dimmed for the computers.txt file. make sure they both match whatever name/path you are using.
you might also try adding
wscript.echo "found file at " & objCurrentFile & " on " & strComputer(i)
right before the
objLogFile2.WriteLine Now & " - The file " & objSearchFile & " was found on " & strComputer(i) & " at " & objCurrentFile
lines, this will make it tell you if it found the file and maybe just isnt writing it to the file.
wscript.echo is great for debugging. maybe set it to wscript.echo strcomputer(i) ” is being searched” when it starts searching it as well, to see if its even picking up the computer names fromt eh input file.
actually, it outputs to the c drive of the machine you run the script from. you can change the path to whatever you want. all the output goes to the one(2, actually, but can easily combine) files. no, it shows lines like this:
The file was found on at
The file was not found on
that was all that i had needed at the time, what more would you need? let me know and i can modify it