Powershell and System.IO.FileSystemWatcher
Asked Answered
C

3

6

I am new to PowerShell and I am trying to use the System.IO.FileSystemWatcher to monitor the presence of a file in a specified folder. However, as soon as the file is detected I want to stop monitoring this folder immediately and stop the FileSystemWatcher. The plan is to incorporate the PowerShell script into a SQL Agent to enable users to restore their own databases. Basically I need to know the command to stop FileSystemWatcher from monitoring as soon as one file is found. Here is the script so far.

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "C:\TriggerBatch"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true  

### DEFINE ACTIONS AFTER A EVENT IS DETECTED
    $action = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), $changeType, $path"
                Add-content "C:\log2.txt" -value $logline              
              }    

### DECIDE WHICH EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY  
    $created = Register-ObjectEvent $watcher Created -Action $action

while ($true) {sleep 1} 

## Unregister-Event Created ??
##Stop-ScheduledTask ??
Counterintelligence answered 3/8, 2015 at 20:11 Comment(0)
B
5
Unregister-Event $created.Id

This will unregister the event. You will probably want to add this to the $action.

Do note that if there are events in the queue they will still be fired.

This might help too.

Bedwell answered 3/8, 2015 at 20:31 Comment(2)
Great, that seems to be working and correctly only identifies the one file. My script is however still running and I need the script to stop running/complete and send a successful message, so that the next step in the SQL Agent can commence. Any ideas? ThanksCounterintelligence
You can set some $flag in the action to $true and change the while to while (-not $flag) {sleep 1} or you can add in the action some thing like $temp = New-Event -SourceIdentifier "Found-File" -MessageData $path and instead of the while do $result = Wait-Event -SourceIdentifier "Found-File"Bedwell
F
2

Scriptblocks that are run as an action on a subscribed event have access to the $Args, $Event, $EventArgs and $EventSubscriber automatic variables.

Just add the Unregister-Event command to the end of your scriptblock, like so:

### DEFINE ACTIONS AFTER A EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
            $changeType = $Event.SourceEventArgs.ChangeType
            $logline = "$(Get-Date), $changeType, $path"
            Add-content "C:\log2.txt" -value $logline  
            Unregister-Event -SubscriptionId $EventSubscriber.SubscriptionId            
          }    

This is the pattern for an event that only performs an action once and then cleans itself up.

It's difficult to effectively explore these automatic variables since they are within the scope of a Job, but you can futz with them by assigning them to global variables while you are sketching out your code. You may also get some joy with Wait-Debugger and Debug-Runspace. In the case of the $EventSubscriber variable, it returns the exact object you get if you run Get-EventSubscriber (having created a single subscription already). That's how I found the SubscriptionId property.

Feudalize answered 11/4, 2018 at 11:4 Comment(0)
A
0

If you want to stop/unregister all registered events you can call

Get-EventSubscriber|Unregister-Event
Amitosis answered 5/5, 2021 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.