Home > Software design >  Register-ObjectEvent cmdlet not working properly on Powershell but working on ISE
Register-ObjectEvent cmdlet not working properly on Powershell but working on ISE

Time:05-28

I am working on a Powershell Script to monitor a folder and when a new item is created the script needs to copy that file to another folder.

The issue I'm experiencing is that when I execute it in Powershell ISE it works perfectly but when executing it on Powershell it only works for the period of time that Powershell window is open (> 1 second).

I tried putting the sleep command at the end, and found that only when the script got ended the action is taken, in this case, when I press CTRL C to stop the script in Powershell, the actions that should have been taken when I created the items are executed all together.

Don't know if I am doing something wrong or just misunderstanding something.

Here is the script i am using to test it:

$Watcher = New-Object System.IO.FileSystemWatcher
$Watcher.path = "\\192.168.5.127\data\TestWatcher"
$Destination = "C:\TestWatcher"
$Watcher | Get-Member -MemberType Event
$Watcher.EnableRaisingEvents = $true

$action = {
    $path = $event.SourceEventArgs.FullPath
    $name = $event.SourceEventArgs.Name
    $changetype = $event.SourceEventArgs.ChangeType
    Write-Host "File $name at path $path was $changetype at $(get-date)"
    Copy-Item $Watcher.path $Destination
}

Register-ObjectEvent $Watcher 'Created' -Action $action

Any help or advice would be appreciated.

Best Regards,

CodePudding user response:

Gregor y provided the crucial hint in a comment:

You can use a Wait-Event call at the end of your script to indefinitely wait for events that will never arrive, which keeps your script running, but - unlike Start-Sleep - does not block processing of events via the script block passed to Register-ObjectEvent's -Action parameter:

$Watcher = New-Object System.IO.FileSystemWatcher
$Watcher.path = "\\192.168.5.127\data\TestWatcher"
$Destination = "C:\TestWatcher"
$Watcher.EnableRaisingEvents = $true

$action = {
    $path = $event.SourceEventArgs.FullPath
    $name = $event.SourceEventArgs.Name
    $changetype = $event.SourceEventArgs.ChangeType
    Write-Host "File $name at path $path was $changetype at $(get-date)"
    Copy-Item $Watcher.path $Destination
}

# Register the event with a self-chosen name passed to -SourceIdentifier
# and an -Action script block.
$null = 
  Register-ObjectEvent $Watcher Created -SourceIdentifier FileWatcher -Action $action

# Now wait indefinitely for an event with the same source identifier to arrive.
# NONE will ever arrive, because the events are handled via the -Action script block.
# However, the call will prevent your script from exiting, without
# blocking the processing of events in the -Action script block.
Wait-Event -SourceIdentifier FileWatcher

Alternatively, make do without an -Action script block and process events in a Wait-Event loop:

$Watcher = New-Object System.IO.FileSystemWatcher
$Watcher.path = "\\192.168.5.127\data\TestWatcher"
$Destination = "C:\TestWatcher"
$Watcher.EnableRaisingEvents = $true

# Register the event with a self-chosen name passed to -SourceIdentifier
# but WITHOUT an -Action script block.
$null = Register-ObjectEvent $Watcher 'Created' -SourceIdentifier FileWatcher

# Now use Wait-Event with the chosen source identifier to
# to indefinitely receive and then process the events as they 
# become available.
while ($event = Wait-Event -SourceIdentifier FileWatcher) {
  $path = $event.SourceEventArgs.FullPath
  $name = $event.SourceEventArgs.Name
  $changetype = $event.SourceEventArgs.ChangeType
  Write-Host "File $name at path $path was $changetype at $(Get-Date)"
  Copy-Item $Watcher.path $Destination
  $event | Remove-Event # Note: Events must be manually removed.
}
  • Related