Difference action for different files - powershell

I want to monitor new files created in a folder.
When this happens I want to launch a batch file (in the example below I just write a line in a log file).
I don't know why this doesn't work.
My code is:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "D:\"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
if ($file.Name -like "Apertura") {
Add-Content "C:\Users\F701845\Desktop\Apertura.txt" -Value $logline
} else {
Add-Content "C:\Users\F701845\Desktop\TestNO.txt" -Value $logline
}
}
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {sleep 5}

Well this one is easy, you are using a variable that is empty in your IF/ELSE.
$path and $changeType are derived from $Event but $file is not existing at all.
First take a look at what you have and you will see that you might be able to use in this case: $Event.SourceEventArgs.Name.
$Event.SourceEventArgs | Get-Member
bool Equals(System.Object obj)
int GetHashCode()
type GetType()
string ToString()
System.IO.WatcherChangeTypes ChangeType {get;}
string FullPath {get;}
string Name {get;}
While it does work, it still looks for files called exactly Apertura meaning Apertura.txt wont work, i would recommend using something like Apertura.* if you do not know the extension.
Example Code:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\test\"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$file = $Event.SourceEventArgs.Name #get filename from Event data
$logline = "$(Get-Date), $changeType, $path"
if ($file -like "Apertura.*") { #removed the .Name and added .*
Add-Content "C:\Users\username\Desktop\Apertura.txt" -Value $logline
} else {
Add-Content "C:\Users\username\Desktop\TestNO.txt" -Value $logline
}
}
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {sleep 5}
$watcher.Dispose() #can be used to dispose the System.IO.FileSystemWatcher

Related

PowerShell IO.FileSystemWatcher doesn't work after restart fileserver

I need a FileSystemWatcher on a network directory (fileserver)
The script works well but fails after a reboot from the fileserver.
How can I detect if the FSW is failing and restart the watcher if the fileserver is up and running again?
Code:
$destinations = #{"\\location1" = "c:\destination1"
"\\location2" = "c:\destination2"
}
foreach ($location in $destinations.Keys) {
$Watcher = New-Object IO.FileSystemWatcher -Property #{
Path = $location
Filter = "*.*"
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $location -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$SI = $Event.SourceIdentifier
Write-Host "The file '$name' was $changeType at $timeStamp"
Write-Host $path
Move-Item $path -Destination $destinations[$SI] -Force -Verbose
}
}
RTFM!
There is Error event from FileSystemWatcher, and there is your case exactly described.
For example, if the object is monitoring changes in a remote directory and the connection to that directory is lost, the Error event is raised.
Solution found:
$destinations = #{"\\location1" = "c:\destination1"
"\\location2" = "c:\destination2"
}
foreach ($location in $destinations.Keys) {
$Watcher = New-Object IO.FileSystemWatcher -Property #{
Path = $location
Filter = "*.*"
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$SI = $Event.SourceIdentifier
Write-Host "The file '$name' was $changeType at $timeStamp"
Write-Host $path
Move-Item $path -Destination $destinations[$SI] -Force -Verbose
}
$actionError = {
$Sender.EnableRaisingEvents = $false
$ip = $location -split "\\" | Where { $_ -ne "" } | Select -first 1
do {
Write-Host "Waiting for boot " + $ip
Start-Sleep -Seconds 5
} until (Test-Connection $ip -Quiet -Count 1)
$Sender.EnableRaisingEvents = $true
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $location -Action $action
Register-ObjectEvent $Watcher -EventName Error -SourceIdentifier $location+'ERROR' -Action $actionError
}

How to make a io.systemfileswatcher run indefinitely

I have a script that calls two io.systemfile watchers which I would like to run 24x7 so that it can detect data that needs to be processed and automatically hand it off to a script that processes it (and uploads the result to the network):
Function Report1Watcher{
param ($folder)
$filter = "*vac*.csv"
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $true
EnableRaisingEvents = $true
InternalBufferSize = 65536
}
Write-Host "Watching $folder for creation of $filter files..."
$changeAction = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$Actionpath = Split-Path $Path
write-host $Actionpath " Ready for Report1"
Report1 $Actionpath
write-host $Actionpath " Report1 Generated"
}
Register-ObjectEvent $Watcher -EventName "Created" -Action $changeAction
}
Function Report2Watcher{
param ($folder)
$filter = "*4.4*"
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $true
EnableRaisingEvents = $true
InternalBufferSize = 65536
}
Write-Host "Watching $folder for creation of $filter files..."
$changeAction = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$Actionpath = Split-Path $Path
$Actionpath = Split-Path $Actionpath
write-host $Actionpath " Ready for Report2"
Report2 $Actionpath
write-host "Report2 Generated"
}
Register-ObjectEvent $Watcher -EventName "Created" -Action $changeAction
}
Function Watchmaster{
Report1Watcher $Testdir
Report2Watcher $Testdir
}
Watchmaster
I am thinking of turning it into a windows service, but would it be able to run 24x7 as is? I'm not sure where I could add an infinite loop without creating infinite io.systemfilewatchers. I know as a PS script that powershell would need to constantly be running. But if I created a batch file that runs this and set it up as a service with nssm would this accomplish what I need?

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.

How to register an event in Powershell so it stays permanent?

I have the below script, that is just supposed to monitor a folder, and when a .xlsx file is created, then it should convert it to a .csv file in another folder. It works on the first file created, but it doesn't work on the next file being created in the folder. How can I get the event to stay permanent?
$ErrorActionPreference = 'Stop'
$folder = 'c:\Users\exgtcl\hotfolder'
$destination = 'c:\Users\exgtcl\targetfolder'
$filter = '*.xlsx'
Function Convert-Csv
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$FullPath
)
$ExcelFiles = Get-ChildItem $FullPath
Write-Host "Working on file '$FullPath' "
$excelApp = New-Object -ComObject Excel.Application
$excelApp.DisplayAlerts = $false
$excelApp.Visible = $false
$workbook = $excelApp.Workbooks.Open($ExcelFiles.FullName)
$newName = "$destination\output.csv"
$workbook.SaveAs($newName, [Microsoft.Office.Interop.Excel.XlFileFormat]::xlCSV)
$workbook.Close()
# Release Excel Com Object resource
$excelApp.Workbooks.Close()
Start-Sleep 2
$excelApp.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelApp) | Out-Null
}
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Convert-Csv -FullPath $path
Start-Sleep 3
Write-Host "moving files"
Move-Item $path -Destination $destination -Force -Verbose
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action $action

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.