Question

Goal: create a file watcher to execute some tasks when a file stops being written to (i.e. file size stops changing or last write hasn't occurred in X time)

I know you can use powershell to create tasks when files are created/deleted/changed/renamed. Is there a way to utilize this to say do something if the file hasn't changed for X time (utilizing powershell or another language)?

    $folder = '<path>' # Enter the root path you want to monitor. 
    $filter = '*.*'  # You can enter a wildcard filter here. 

    # In the following line, you can change 'IncludeSubdirectories to $true if required.                           
    $fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 

    # Here, all three events are registerd.  You need only subscribe to events that you need: 

    Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
    $name = $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    Write-Host "The file '$name' was $changeType at $timeStamp" -fore green 
    Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

    Register-ObjectEvent $fsw Deleted -SourceIdentifier FileDeleted -Action { 
    $name = $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    Write-Host "The file '$name' was $changeType at $timeStamp" -fore red 
    Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

    Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action { 
    $name = $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    Write-Host "The file '$name' was $changeType at $timeStamp" -fore white 
    Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

    # To stop the monitoring, run the following commands: 
    # Unregister-Event FileDeleted 
    # Unregister-Event FileCreated 
    # Unregister-Event FileChanged
Was it helpful?

Solution

I don't know of an event type you can use to trigger that, but you can start a process like this on change or creation:

while ($true)
 {
   try{ 
        [IO.file]::openwrite(<filepath>).close()
        break
      }

   catch { start-sleep -Seconds 5 }
 }

 do-stuff

As long as the file is being written to you won't be able to get a write lock, and the openwrite will throw an error. As soon as it's closed, the openwrite will succeed, break the loop and fall through to the rest of the script.

OTHER TIPS

Waiting for events won't help you when you're checking for the absence of events for a defined period of time. You can check the LastWriteTime property to see if the file has been changed in a given timespan:

$threshold = 5  # minutes

$f = Get-Item 'C:\path\to\your.file'

if (((Get-Date) - $f.LastWriteTime).TotalMinutes -lt $threshold) {
  'File has been changed.'
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top