External powershell scripts only run once when action called - powershell

I am trying to call an outside ps script to run every time files are created. The monitoring and logging of files work well, but the Invoke-Expression of running the external script only runs one time even if more files are created. How do I run the external script with every time a new file is created.
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\mypath"
$watcher.Filter = "*.txt*"
$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 "C:\mypath\log.txt" -value $logline
Invoke-Expression (start powershell ("C:\MyOtherScript.ps1")) ###### This only runs one time even if file is changes and logged
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {sleep 5}
EDIT: This got it working incase anyone find themselves here looking to solve the porblem
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\mypath"
$watcher.Filter = "*.txt*"
$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 "C:\mypath\log.txt" -value $logline
Start-Process powershell -argument "C:\MyOtherScript.ps1"
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
#while ($true) {sleep 5}

Invoke-Expression is not recommend over using & due to security concerns. In your example, however, I'd suggest Start-Process:
Start-Process -FilePath 'powershell' -ArgumentList #('-File','"C:\MyOtherScript.ps1"')

Related

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 filter option - Not working.

I would like to watch out for files having name like "today's date then 6digits then _ABC_XYZ.csv". For e.g. if today's date is 20181011 then the file should be the name: 20181011123456_ABC_XYZ.csv. Below is my code:
$DateStr = $Date.ToString("yyyyMMdd")
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "E:\\Sid\\source"
$watcher.Filter = $DateStr + "\d\d\d\d\d\d*_Recon_ForeignExchange.csv"
$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:\log.txt" -value $logline
}
### 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}
My Queries:
Its seems that the $watcher.filter is not working as it's taking files other than the one given in the filter as well.
Also I would like to watch 2 folders at a time as the file can come in any of the folders. How do I achieve this?
As #Theo pointed out, the Filter property does not support regex. Only path wildcards are allowed.
You will have to use a simpler wildcard in your filter:
# rough wildcard filter
$watcher.Filter = "*_Recon_ForeignExchange.csv"
..and then perform a more specific (regex) check in your handler:
$action = {
$path = $Event.SourceEventArgs.FullPath
# check if the file name has the desired format
if ((Split-Path $path -Leaf) -match ($DateStr + "\d\d\d\d\d\d*_Recon_ForeignExchange.csv"))
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "D:\log.txt" -value $logline
}
}
As for the other directory, #vrdse already pointed out that you're going to need a 2nd watcher for that.

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
}

Powershell : FileSystemWatcher for filename change

I tried using this code to monitor filename changes on our fileserver. But I only want to trigger the event when the extension changes.
Any suggentions?
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "E:\"
# $watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$Name = $Event.SourceEventArgs.Name
$logline = "$(Get-Date), $changeType, $path, $name"
Add-content "E:\log.txt" -value $logline
}
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}
Set the NotifyFilter property in the $watcher variable to FileName only.
$watcher.NotifyFilter = 'FileName'
Now the action will only trigger for file name changes.

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