Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File Watcher with Powershell not triggering always

I am trying to create a File Watcher with Powershell. Need it to run a PHP-Script of mine as soon as a file was changed. My first thought was that everything works perfectly but seems like it just triggers once.

As soon as I change a *.js file in the given folder the PHP-Script triggers. But it only triggers one time. I changed the file again a few minutes later, but the php script wasn't execute anymore (even the Write-Host didn't anything).

Here is my Powershell-Script:

#By BigTeddy 05 September 2011 

#This script uses the .NET FileSystemWatcher class to monitor file events in folder(s). 
#The advantage of this method over using WMI eventing is that this can monitor sub-folders. 
#The -Action parameter can contain any valid Powershell commands.  I have just included two for example. 
#The script can be set to a wildcard filter, and IncludeSubdirectories can be changed to $true. 
#You need not subscribe to all three types of event.  All three are shown for example. 
# Version 1.1 

$global:folder = 'C:\Users\Dario\Desktop\scripts' # Enter the root path you want to monitor. 
$filter = '*.js'  # 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 
} 

Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action { 
$name = $Event.SourceEventArgs.Name 
$changeType = $Event.SourceEventArgs.ChangeType 
$timeStamp = $Event.TimeGenerated 
$path = $global:folder + "\" + $name

    Try {
        Write-Host "The file '$name' was $changeType at $timeStamp" -fore white 
        cmd.exe /k ""C:\Users\Dario\Desktop\mep\script.bat" "$path""
    } Catch {
        Write-Host "Problems"
    }
} 

# To stop the monitoring, run the following commands: 
# Unregister-Event FileDeleted 
# Unregister-Event FileCreated 
# Unregister-Event FileChanged
like image 699
Sylnois Avatar asked Jan 16 '26 22:01

Sylnois


1 Answers

Interesting question! I started Googling for this and found this ready made function for it:

Function Start-FileSystemWatcher {
    [cmdletbinding()]
    Param (
        [string]$Path,
        [parameter()]
        [ValidateSet('Changed','Created','Deleted','Renamed')]
        [string[]]$EventName,
        [string]$Filter,
        [parameter()]
        [System.IO.NotifyFilters]$NotifyFilter,
        [switch]$Recurse,
        [scriptblock]$Action
    )

    $FileSystemWatcher  = New-Object  System.IO.FileSystemWatcher

    If (-NOT $PSBoundParameters.ContainsKey('Path')){
        $Path  = $PWD
    }

    $FileSystemWatcher.Path = $Path

    If ($PSBoundParameters.ContainsKey('Filter')) {
        $FileSystemWatcher.Filter = $Filter
    }

    If ($PSBoundParameters.ContainsKey('NotifyFilter')) {
        $FileSystemWatcher.NotifyFilter =  $NotifyFilter
    }

    If ($PSBoundParameters.ContainsKey('Recurse')) {
        $FileSystemWatcher.IncludeSubdirectories =  $True
    }

    If (-NOT $PSBoundParameters.ContainsKey('EventName')){
        $EventName  = 'Changed','Created','Deleted','Renamed'
    }

    If (-NOT $PSBoundParameters.ContainsKey('Action')){
        $Action  = {

        Switch  ($Event.SourceEventArgs.ChangeType) {
            'Renamed' {
                $Object  = "{0} was  {1} to {2} at {3}" -f $Event.SourceArgs[-1].OldFullPath,
                $Event.SourceEventArgs.ChangeType,
                $Event.SourceArgs[-1].FullPath,
                $Event.TimeGenerated
            }
            Default {
                $Object  = "{0} was  {1} at {2}" -f $Event.SourceEventArgs.FullPath,
                $Event.SourceEventArgs.ChangeType,
                $Event.TimeGenerated
            }
        }

        $WriteHostParams  = @{
            ForegroundColor = 'Green'
            BackgroundColor = 'Black'
            Object =  $Object
        }

        Write-Host  @WriteHostParams
        }
    }

    $ObjectEventParams  = @{
        InputObject =  $FileSystemWatcher
        Action =  $Action
    }

    ForEach  ($Item in  $EventName) {
        $ObjectEventParams.EventName = $Item
        $ObjectEventParams.SourceIdentifier =  "File.$($Item)"
        Write-Verbose  "Starting watcher for Event: $($Item)"
        $Null  = Register-ObjectEvent  @ObjectEventParams
    }
}

Start-FileSystemWatcher -Path 'C:\Users\me\Downloads\Input_Test' -EventName Changed -Filter '*.js'

It seems to do exactly what you want...

like image 74
DarkLite1 Avatar answered Jan 19 '26 10:01

DarkLite1



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!