VBscript to check for the existance of a file (with the ability to use a wildcard) within a certain time frame

16,080

Solution 1

If you use WMI, it supports wildcards.

Dim strPath

strFile = "*.*"
If WScript.Arguments.Count > 1 Then
    strPath = WScript.Arguments.Item(0)
    strFile = WScript.Arguments.Item(1)
Elseif WScript.Arguments.Count = 1 Then
    strPath = WScript.Arguments.Item(0)
Else

End If

Set objFso = CreateObject("Scripting.FileSystemObject")
If Not objFso.FolderExists(strPath) Then
    WScript.Echo "Folder path does not exist."
    WScript.Quit
Else
    'Remove any trailing slash
    If Right(strPath, 1) = "\" Then
        strPath = Left(strPath, Len(strPath) - 1)
    End If
End If
Set objFso = Nothing

If Not IsNull(strPath) And strPath <> "" Then
    strQuery = strPath & "\" & strFile
Else
    strQuery = strFile
End If

strQuery = Replace(strQuery, "*", "%")
strQuery = Replace(strQuery, "?", "_")

strQuery = Replace(strQuery, "\", "\\")

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}\\" & strComputer & "\root\cimv2")

Set colFiles = objWMIService.ExecQuery _
    ("Select * From CIM_DataFile Where FileName Like '" & strQuery & "'")

For Each objFile in colFiles
    WScript.Echo "Access mask: " & objFile.AccessMask
    WScript.Echo "Archive: " & objFile.Archive
    WScript.Echo "Compressed: " & objFile.Compressed
    WScript.Echo "Compression method: " & objFile.CompressionMethod
    WScript.Echo "Creation date: " & objFile.CreationDate
    WScript.Echo "Computer system name: " & objFile.CSName
    WScript.Echo "Drive: " & objFile.Drive
    WScript.Echo "8.3 file name: " & objFile.EightDotThreeFileName
    WScript.Echo "Encrypted: " & objFile.Encrypted
    WScript.Echo "Encryption method: " & objFile.EncryptionMethod
    WScript.Echo "Extension: " & objFile.Extension
    WScript.Echo "File name: " & objFile.FileName
    WScript.Echo "File size: " & objFile.FileSize
    WScript.Echo "File type: " & objFile.FileType
    WScript.Echo "File system name: " & objFile.FSName
    WScript.Echo "Hidden: " & objFile.Hidden
    WScript.Echo "Last accessed: " & objFile.LastAccessed
    WScript.Echo "Last modified: " & objFile.LastModified
    WScript.Echo "Manufacturer: " & objFile.Manufacturer
    WScript.Echo "Name: " & objFile.Name
    WScript.Echo "Path: " & objFile.Path
    WScript.Echo "Readable: " & objFile.Readable
    WScript.Echo "System: " & objFile.System
    WScript.Echo "Version: " & objFile.Version
    WScript.Echo "Writeable: " & objFile.Writeable
Next

EDIT..........

You can use a WMI event script with the __InstanceCreationEvent to monitor for new file creation in a specific folder. It looks like this:

strSource = "C:\\somefilepath\\withdoubleshlashes"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & strComputer & "rootcimv2")

Set colEvents = objWMIService.ExecNotificationQuery _
    ("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
        & "Targetinstance ISA 'CIM_DirectoryContainsFile' AND " _
        & "TargetInstance.GroupComponent= " _
        & "'Win32_Directory.Name=""" & strSource & """'")

Do While True
    Set objEvent = colEvents.NextEvent()
    copyFile(objEvent.TargetInstance.PartComponent)
Loop

For a full explanation, you can read Monitoring and Archiving Newly Created Files on my blog.

Solution 2

This answer uses Regular Expressions. To make it work it rewrites your pattern format into regular expression format. e.g. *.txt will become ^.*[.]txt$.

The following lists text files in C:\Temp last modified between 5:55 AM and 6:05 AM:

strPath = "C:\Temp"
strFile = "*.txt"
startTime = 555
endTime = 605

Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(strPath)
Set files = folder.Files

Set re = New RegExp
re.IgnoreCase = true
re.Pattern = "^" + Replace(Replace(strFile, ".", "[.]"), "*", ".*") + "$"

For Each f in Files
  Set matches = re.Execute(f.Name)
  If matches.Count > 0 Then
    HM = Hour(f.DateLastAccessed) * 100 + Minute(f.DateLastAccessed)
    If HM >= startTime And HM <= endTime Then
      WScript.Echo f.Name, f.DateLastAccessed
    End If
  End If
Next

References:

Share:
16,080
Th3Cap3
Author by

Th3Cap3

Updated on June 14, 2022

Comments

  • Th3Cap3
    Th3Cap3 almost 2 years

    Good morning all, I have been trying to pull together a VBscript that takes a file path and a file name (that may have a wildcard in it) from the user when the script is exicuted. The script will then check the specified directory for a file that matches the provided file name and then looks at the last modified date to see if it was created/modified within a certain time frame (i.e. 6am plus or minus 5 minutes). It would then copy said file into a zip file.

    So far I have been able to get the arguments working, and I have it setup to grab the current time, look at the files in the folder and match a hard coded filename to one in the folder. This is what I have thus far.

    currentTime = Now()
    
    filePath = Wscript.Arguments.Item(0)
    fileName = Wscript.Arguments.Item(1)
    
    Set fileSystem = CreateObject("Scripting.FileSystemObject")
    Set directory = fileSystem.GetFolder(filePath)
    
    For each file in directory.Files
        If file.Name = fileName Then
            Wscript.echo file.Name & " " & file.DateLastModified
        end if
    Next
    

    I am a VBscript noob and I am looking forward to learning the way!

    Cap3

  • AutomatedChaos
    AutomatedChaos over 11 years
    When you are working with WMI services, it enables you to connect it to an event sink. Now you can handle the event really event-based.
  • Nilpo
    Nilpo over 11 years
    Using an event sink here would be the preferred method (as it uses much less overhead), however, the OP does not provide enough information to leverage an event sink. Though it sounds as if using an __InstanceCreationEvent to monitor a specific folder during specific minutes of the day might accomplish the intended task.
  • Th3Cap3
    Th3Cap3 over 11 years
    This _InstanceCreationEvent will watch for the creation of a file in a specific location? If that is what it does, that could be extremely helpful. I wish I could have been more precise in my post, however I wasn't given much detail on the request either, I am still waiting for more information on how the files are named, when it comes in, if it's deleted, etc... Could you expand on the InstanceCreationEvent?
  • Nilpo
    Nilpo over 11 years
    Yes, the __InstanceCreationEvent can be used to monitor for the creation of a file in a specific location. You just need to know the file path. See my edit above.
  • Th3Cap3
    Th3Cap3 over 11 years
    That is very helpful :-), I am going to play with this and see if I can grasp how it flows into the other stuff I wish to do with the script, thank you for your help!
  • Nilpo
    Nilpo over 11 years
    No problem at all. Glad I could help out.
  • Dss
    Dss about 10 years
    Something noticed with the __InstanceCreationEvent method is that you can really only reliably monitor a single folder. Adding more folders by either running multiple copies of a script or adding more OR values to the where clause both end with a "quote violation". My memory value for WMI quota is set for 512MB which is the recommended value by microsoft, but I am going to try 1GB to see if that works better. Still I think maybe an FSO solution is best overall if possible, regardless of how nice the instance creation event feature is on paper.
  • Nilpo
    Nilpo about 10 years
    @Dss The __InstanceCreationEvent is system-wide. There's no need to create more than one instance of the event loop. Instead, leave off the directory portion and then check each result you get back for the proper directory or directories.
  • Dss
    Dss about 10 years
    @Nilpo You misunderstand... Im talking about monitoring multiple folder paths. If I want to monitor C:\ I can do objWMIService.ExecNotificationQuery("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent='Win32_Directory.Name=""C:\\\\‌​""'") and that works fine every time. But If I want to do C:, D:, & E:\ I can either run 3 scripts of the same code with separate drives, or alter the query in the single script to use C "OR" D but either way tends to hit the quota limit and doesn't reliably catch the create event.
  • Nilpo
    Nilpo about 10 years
    @Dss Leave off this part TargetInstance.GroupComponent='Win32_Directory.Name=""C:\\\\‌​""'" altogether. Then use an If statement to check each instance for the paths you want to monitor. Your query should just be "SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'CIM_DirectoryContainsFile'". That said, checking multiple drives could cause memory issues depending upon how much space is used.
  • Dss
    Dss about 10 years
    @Nilpo Thanks I'll try that
  • Dss
    Dss about 10 years
    @Nilpo Ok Tried your way.. immediately hits the quota violation upon startup. I think monitoring so many events without a clause just overloads it. It only seems to work with a single drive when I use the TargetInstance.GroupComponent='Win32_Directory.Name=""C:\\\\‌​""'". I'll have to try a purely vbs method to do more than one.
  • Nilpo
    Nilpo about 10 years
    @Dss Are these large drives? Maybe it's time to find a third-party COM component that can monitor new files more efficiently than WMI.
  • Dss
    Dss about 10 years
    @Nilpo Yes these are very large drives.. 2 of them are network drives mapped to a drive letter. They all work fine on their own.. but any combination or attempt to monitor more than one or a larger recordset seems to bring wmi to its knees. I created a simple vbs that works fine. Thanks!