Powershell script not firing Register-ObjectEvent - powershell

I have the below script for folder watcher:
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\inetpub\wwwroot\exports\"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
start-process C:\inetpub\wwwroot\exports\services\execute.bat
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 1}
The above script monitors C:\inetpub\wwwroot\exports\ folder and if there is any change to this folder, the $action is called. This script is not working and I see "Not started" error as below:
Any help on how to fix this?

I think its a "feature", the $action script should fire. It only seems to enter Running state after the first event has been fired.
Temporarily insert below before while ($true) {sleep 1} and you should see the state change:
Get-Job
Set-Content -Path "$($watcher.Path)\a_test_file.txt" -Value "hello"
Get-Job
(And for the sake of completeness Get-Job -Id 1 | Stop-Job -PassThru | remove-Job to stop and remove job id #1 - change id as required)

Related

Powershell: Register-ObjectEvent io.filesystemwatcher - Can a single registration watch for created and renamed?

I have something like this snippet:
$Watcher = New-Object IO.FileSystemWatcher $folder_to_watch, $file_name_filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $eventname -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$fileextension = [System.IO.Path]::GetExtension($name) # extract extension as string from filename
$changeType = $Event.SourceEventArgs.ChangeType
Right now, this event only fires on file creation.
I want it to fire both on creation and rename.
I tried this:
Register-ObjectEvent $Watcher -EventName 'Created,Renamed'
But this does not work a syntax error is raised:
"Register-ObjectEvent : Cannot register for the specified event. An
event with the name 'Created,Renamed' does not exist. Parameter
name: eventName
Is that possible (and how is it done), or must I declare two events?
(It is not clear from the docs if this is possible, or how to do it in powershell)
SOLUTION
The answer below from HAL9256 is valid. However, before discovering that path, I modified the event type to "changed"
This catches file creation and file rename (and some other things). Since my action code filters to make sure only desired files are actually processed, the event type of "changed" meets my needs at this time.
The short answer is that you can only subscribe to one event at a time.
But you can have multiple subscribed events registered to the same Action. For ex. If you define your action in a Script Block, you can subscribe both Created and Rename to the same Action.
$Watcher = New-Object IO.FileSystemWatcher $folder_to_watch, $file_name_filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
#Your script block
$Action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$fileextension = [System.IO.Path]::GetExtension($name) # extract extension as string from filename
$changeType = $Event.SourceEventArgs.ChangeType
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $eventname -Action $Action
Register-ObjectEvent $Watcher -EventName Renamed -SourceIdentifier $eventname -Action $Action

Powershell - how to start action after a FEW files have been created

i want to loop a powershell script that monitors if a few xml files were created in a folder. If there are at least 3 it should restart a program.
Here is what i got from the use nixda on here:
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\DVNAV\11842596\nav2016\2019"
$watcher.Filter = "*.xml*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { Stop-Process -name dvnav -force
Start-Sleep -Seconds 8
Start-Process -FilePath 'C:\Program Files (x86)\DVNAV.exe' -verb RunAs
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}
But i don't know how i can set the monitoring to multiple files not just one.
This should work for you. Don't Forget to unregister Events after using/testing!
#--------------------------------------------------
function Stop-EventWatcher {
#--------------------------------------------------
# To stop the monitoring, run the following commands:
Unregister-Event FileCreated
}
$folderToWatch = 'C:\DVNAV\11842596\nav2016\2019'
$filter = '*.xml'
$script:counter = 0
# In the following line, you can change 'IncludeSubdirectories to $true if required.
$fsw = New-Object IO.FileSystemWatcher
$fsw.Path = $folderToWatch
$fsw.IncludeSubdirectories = $false
$fsw.EnableRaisingEvents = $true
$scriptBlock = {
$message = $event.MessageData # message data is how we pass in an argument to the event script block
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$script:counter++
if( $script:counter -eq 3 ) {
$script:counter = 0
# do special action here!
}
}
# Here, the event ist registered. You need only subscribe to events that you need:
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -MessageData 'Hello' -Action $scriptBlock

PowerShell FileSystemWatcher exit while ($true)

I need this script to loop until it does the action but I can't seem to break the loop.
# SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\TransX\InputTriggers\"
$watcher.Filter = "IVANS_TRIGGER_FILE.trig"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
# DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, Ivans File Arrived"
Add-Content "C:\TransX\InputTriggers\ProcessLog.txt" -Value $logline
Start-Process C:\TransX\Transxdl.bat
Remove-Item C:\TransX\InputTriggers\IVANS_TRIGGER_FILE.trig
break
}
# DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
#Register-ObjectEvent $watcher "Changed" -Action $action
#Register-ObjectEvent $watcher "Deleted" -Action $stopScript
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}
The break command in the $action isn't working.
BREAK and CONTINUE will only work this way when used inside a loop, your action is not in the loop itself.
What you could try, is using a variable like $ContinueWatching for your loop and switch it from the Action.
Example:
$ContinueWatching = $true
$Action = {
# <Your code here>
# <Remove break>
# StopWatching and Exit Script
$global:ContinueWatching = $false
}
While ($ContinueWatching) {
Start-Sleep -s 1
}

how to monitor a folder in windows a run a batch file

I was following this SO answer to monitor a folder , but it is working one time. I mean if create a folder or file the batchfile will run , I created again a folder or edite it , it wont trigger
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\uuu\Desktop\new folder\tttt"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "D:\Copyof\PSlog.txt" -value $logline
cmd.exe /k "D:\Copyof\move.bat"
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 1}
Just so this gets an official answer:
Isn't the problem coming from your "/k" flag on cmd.exe? It means execute the command and remain. – David Brabant
/K Run Command and then return to the CMD prompt. This is useful for testing, to examine variables – Matt
Use a /C instead. – SomethingDark

Check for file creation in a loop

Can I run this script one time automate when the .exe show up on folder?
Get-ChildItem -Filter *.exe | ForEach {
&$_.Fullname /s
I want a script to check if .exe file shows up on folder, then run that commands, else check again for .exe file.
You can use the FileSystemWatcher to listen for these events.
Get-EventSubscriber -SourceIdentifier ExeCreated -ErrorAction SilentlyContinue | Unregister-Event;
$Watcher = New-Object -TypeName System.IO.FileSystemWatcher;
$Watcher.Filter = '*.exe';
$Watcher.Path = 'c:\test';
$Action = { Write-Host -Object ('New file created: {0}' -f $event.SourceArgs[1].Name); };
Register-ObjectEvent -InputObject $Watcher -EventName Created -Action $Action -SourceIdentifier ExeCreated;