Forum Discussion
Help with Watcher
- Sep 22, 2023
Turion986 Ok... I found another script example and rewrote it again for you... I had some issues with files being renamed repeatedly and added renamed to the filename to exclude that...
#https://dotnet-helpers.com/powershell/how-to-monitor-a-folder-changes-using-powershell/ ### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO $filewatcher = New-Object System.IO.FileSystemWatcher #Mention the folder to monitor $filewatcher.Path = "C:\Test" $filewatcher.Filter = "*.msg" $log = "C:\Test\FileWatcher_log.txt" #include subdirectories $true/$false $filewatcher.IncludeSubdirectories = $true $filewatcher.EnableRaisingEvents = $true ### DEFINE ACTIONS AFTER AN EVENT IS DETECTED $writeaction = { $path = $Event.SourceEventArgs.FullPath $changeType = $Event.SourceEventArgs.ChangeType if (-not ($path -match 'renamed')) { $now = Get-Date -Format "yyyyMMddHHmm" $filename = [System.IO.Path]::GetFileNameWithoutExtension($path) $extension = [System.IO.Path]::GetExtension($path) $newname = "${now}_renamed_${filename}${extension}" Rename-Item -Path $path -NewName $newname $logline = "$(Get-Date), $changeType, $path, $newname" Add-content $log -value $logline } } ### DECIDE WHICH EVENTS SHOULD BE WATCHED #The Register-ObjectEvent cmdlet subscribes to events that are generated by .NET objects on the local computer or on a remote computer. #When the subscribed event is raised, it is added to the event queue in your session. To get events in the event queue, use the Get-Event cmdlet. Register-ObjectEvent $filewatcher "Created" -Action $writeaction Register-ObjectEvent $filewatcher "Changed" -Action $writeaction Register-ObjectEvent $filewatcher "Renamed" -Action $writeaction while ($true) { Write-Host ("Monitoring folder {0}" -f $filewatcher.Path) Start-Sleep 5 }Logfile:
09/22/2023 21:00:45, Renamed, C:\Test\test1.msg, 202309222100_renamed_test1.msg
09/22/2023 21:00:45, Renamed, C:\Test\test1.msg, 202309222100_renamed_test1.msg
09/22/2023 21:01:00, Renamed, C:\Test\test2.msg, 202309222101_renamed_test2.msg
09/22/2023 21:01:00, Renamed, C:\Test\test2.msg, 202309222101_renamed_test2.msg
09/22/2023 21:01:20, Renamed, C:\Test\Testfolder\test3.msg, 202309222101_renamed_test3.msg
09/22/2023 21:01:20, Renamed, C:\Test\Testfolder\test3.msg, 202309222101_renamed_test3.msg
09/22/2023 21:01:41, Renamed, C:\Test\Testfolder\Testsubfolder\test5.msg, 202309222101_renamed_test5.msg
09/22/2023 21:01:41, Renamed, C:\Test\Testfolder\Testsubfolder\test5.msg, 202309222101_renamed_test5.msg09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
Logging is doubled, tripled per file... I'm not sure why that is happening... Is this something you can work with?
Harm_Veenstra that´s even more strange....i only changed the name of the variables from Italian to English........i cannot understand what can be the reason.....
- Sep 28, 2023That seems to work, and this would skip files having rename it it and does only skip files with _renamed_ in the filename (I just tested it)
- Turion986Sep 28, 2023Copper Contributor
Harm_Veenstra only to let you know...
maybe.....i found a little workaround..... i change the operator from match to like
$path = $Event.SourceEventArgs.FullPath $changeType = $Event.SourceEventArgs.ChangeType if (-not ($path -like '*_renamed_*')) {do you see any problems with this solution that i am not aware of?
- Sep 28, 2023Yes, that's the downside... If you have a filename with "rename" it will skip that. Please mark my answer with the rewritten scripts as Best Response & Like to mark this topic as solved
- Turion986Sep 28, 2023Copper Contributor
Harm_Veenstra this is working very fine and at the moment is stable....also the Log File is clear, not doubled as on your side, but in any case i will take a look again when the log will be more full...
there is only a little problem that i found during the test.....is the name of the TAG......
basically if i will create a new test file "renamed_contract.msg" it is obviuosly skipped.
i will try to find a workaround to avoid it.....
- Sep 22, 2023
Turion986 Ok... I found another script example and rewrote it again for you... I had some issues with files being renamed repeatedly and added renamed to the filename to exclude that...
#https://dotnet-helpers.com/powershell/how-to-monitor-a-folder-changes-using-powershell/ ### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO $filewatcher = New-Object System.IO.FileSystemWatcher #Mention the folder to monitor $filewatcher.Path = "C:\Test" $filewatcher.Filter = "*.msg" $log = "C:\Test\FileWatcher_log.txt" #include subdirectories $true/$false $filewatcher.IncludeSubdirectories = $true $filewatcher.EnableRaisingEvents = $true ### DEFINE ACTIONS AFTER AN EVENT IS DETECTED $writeaction = { $path = $Event.SourceEventArgs.FullPath $changeType = $Event.SourceEventArgs.ChangeType if (-not ($path -match 'renamed')) { $now = Get-Date -Format "yyyyMMddHHmm" $filename = [System.IO.Path]::GetFileNameWithoutExtension($path) $extension = [System.IO.Path]::GetExtension($path) $newname = "${now}_renamed_${filename}${extension}" Rename-Item -Path $path -NewName $newname $logline = "$(Get-Date), $changeType, $path, $newname" Add-content $log -value $logline } } ### DECIDE WHICH EVENTS SHOULD BE WATCHED #The Register-ObjectEvent cmdlet subscribes to events that are generated by .NET objects on the local computer or on a remote computer. #When the subscribed event is raised, it is added to the event queue in your session. To get events in the event queue, use the Get-Event cmdlet. Register-ObjectEvent $filewatcher "Created" -Action $writeaction Register-ObjectEvent $filewatcher "Changed" -Action $writeaction Register-ObjectEvent $filewatcher "Renamed" -Action $writeaction while ($true) { Write-Host ("Monitoring folder {0}" -f $filewatcher.Path) Start-Sleep 5 }Logfile:
09/22/2023 21:00:45, Renamed, C:\Test\test1.msg, 202309222100_renamed_test1.msg
09/22/2023 21:00:45, Renamed, C:\Test\test1.msg, 202309222100_renamed_test1.msg
09/22/2023 21:01:00, Renamed, C:\Test\test2.msg, 202309222101_renamed_test2.msg
09/22/2023 21:01:00, Renamed, C:\Test\test2.msg, 202309222101_renamed_test2.msg
09/22/2023 21:01:20, Renamed, C:\Test\Testfolder\test3.msg, 202309222101_renamed_test3.msg
09/22/2023 21:01:20, Renamed, C:\Test\Testfolder\test3.msg, 202309222101_renamed_test3.msg
09/22/2023 21:01:41, Renamed, C:\Test\Testfolder\Testsubfolder\test5.msg, 202309222101_renamed_test5.msg
09/22/2023 21:01:41, Renamed, C:\Test\Testfolder\Testsubfolder\test5.msg, 202309222101_renamed_test5.msg09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
09/22/2023 21:03:08, Created, C:\Test\test6.msg, 202309222103_renamed_test6.msg
Logging is doubled, tripled per file... I'm not sure why that is happening... Is this something you can work with? - Turion986Sep 22, 2023Copper Contributor
Harm_Veenstra is nice to learn every day something new.... i tried to take it to the next step....
obviusly something is again missing.....but at least seems to be stable.
# setting the monitoring folder $Path = "C:\TEST" # setting file filter to monitor $FileFilter = '*.msg' # setting subfolders $IncludeSubFolders = $true # set the file or folder proprieties to monitor $AttributeFilter = [IO.NotifyFilters]::FileName, [IO.NotifyFilters]::LastWrite # set the change to monitor $ChangeTypes = [System.IO.WatcherChangeTypes]::Created # waiting time (ms) $Timeout = 1000 #Funtion called for each file creation function Invoke-SomeAction{ param( [Parameter(Mandatory)] [System.IO.WaitForChangedResult] $ChangeInformation )# closing param Write-Warning 'New File detected:' $ChangeInformation | Out-String | Write-Host -ForegroundColor DarkYellow if($result.ChangeType -ne 0){ Invoke-RenameFile -ChangeInformation $result } }# closing Invoke-SomeAction function Invoke-RenameFile{ param( [Parameter(Mandatory)] [System.IO.WaitForChangedResult] $ChangeInformation )# closing param $now = Get-Date -Format "yyyyMMddHHmm" $file = $result.Name $FileName = [System.IO.Path]::GetFileNameWithoutExtension($file) $Extension = [System.IO.Path]::GetExtension($file) $NewName = "${now}_${FileName}${Extension}" Rename-Item -Path $file -NewName $NewName Write-Warning 'File Renamed:' Write-Host "$NewName" }#closing Invoke-RenameFile #try to unlock the systemwatcher from the CTRL+C abort try { Write-Warning "FileSystemWatcher is monitoring $Path" #create a FileSystemWatcher object $watcher = New-Object -TypeName IO.FileSystemWatcher -ArgumentList $Path, $FileFilter -Property @{ IncludeSubdirectories = $IncludeSubfolders NotifyFilter = $AttributeFilter } } catch [system.exception]{ } # start monitoring manually do { $result = $watcher.WaitForChanged($ChangeTypes, $Timeout) if($results.TimedOut){continue} Invoke-SomeAction -ChangeInformation $result }while ($true) finally { #release the watcher $watcher.Dispose() Write-Warning 'FileSystemWatcher removed.' }can you please take a look also here?
- Sep 21, 2023In the example from the page it's " $result = $watcher.WaitForChanged($ChangeTypes, $Timeout)", but your script has " $results = $watcher.WaitForChanged($ChangeTypes, $Timeout)" (results instead of result)
- Turion986Sep 21, 2023Copper Contributor
Harm_Veenstra thank you...this seems more clean code...
now.....i have another little problem that i cannot understand....i used the code below, using the page that you sent me before.....
# setting the monitoring folder $Path = "C:\TEST" # setting file filter to monitor $FileFilter = '*.msg' # setting subfolders $IncludeSubFolders = $true # set the file or folder proprieties to monitor $AttributeFilter = [IO.NotifyFilters]::FileName, [IO.NotifyFilters]::LastWrite # set the change to monitor $ChangeTypes = [System.IO.WatcherChangeTypes]::Created # waiting time (ms) $Timeout = 1000 #Funtion called for each file creation function Invoke-SomeAction{ param( [Parameter(Mandatory)] [System.IO.WaitForChangedResult] $ChangeInformation )# closing param Write-Warning 'New File detected:' $ChangeInformation | Out-String | Write-Host -ForegroundColor DarkYellow }# closing Invoke-SomeAction #try to unlock the systemwatcher from the CTRL+C abort try { Write-Warning "FileSystemWatcher is monitoring $Path" #create a FileSystemWatcher object $watcher = New-Object -TypeName IO.FileSystemWatcher -ArgumentList $Path, $FileFilter -Property @{ IncludeSubdirectories = $IncludeSubfolders NotifyFilter = $AttributeFilter } } catch [system.exception]{ } # start monitoring manually do { $results = $watcher.WaitForChanged($ChangeTypes, $Timeout) if($results.TimedOut){continue} Invoke-SomeAction -Change $result }while ($true) finally { #release the watcher $watcher.Dispose() Write-Warning 'FileSystemWatcher removed.' }but...error again....
WARNING: FileSystemWatcher is monitoring C:\TEST Invoke-SomeAction : Cannot process argument transformation on parameter 'ChangeInformation'. Cannot convert null to type "System.IO.WaitForChangedResult". At line:53 char:35 + Invoke-SomeAction -Change $result + ~~~~~~~ + CategoryInfo : InvalidData: (:) [Invoke-SomeAction], ParameterB indingArgumentTransformationException + FullyQualifiedErrorId : ParameterArgumentTransformationError,Invoke-Some Actionbut i cannot understand why......
- Sep 19, 2023This seems an option, you can put the rename things in the invoke-someaction part. https://powershell.one/tricks/filesystem/filesystemwatcher
- Turion986Sep 13, 2023Copper Contributormaybe.....this is over my programming knowledge.......do you have suggestions for where and what to look/search for? Even if i search other solutions, i don´t want to implement 3rd part software on our fileserver.....
- Sep 12, 2023I have no clue, I have the same issue... I think it's because you have multiple events registered now. Perhaps rewriting it using examples from a blog post would be better than trying to fix this?
- Turion986Sep 12, 2023Copper Contributor
Harm_Veenstra it worked only for the first file...........than nothing again i only copied paste the code......
- Sep 12, 2023
Ok, the last copy/paste of your script doesn't work:
# Cartella da monitorare (stessa cartella) $FolderToMonitor = "C:\TEST" # Crea un registro per i file già rinominati $RenRegFile = "C:\TEST\registro.txt" function Rename-FileMSG { param ( [string]$file ) Start-Transcript C:\test\script.log if ($file -match "\.msg$" -and -not $RenRegFile.Contains($file)) { $now = Get-Date -Format "yyyyMMddHHmm" $nameFile = [System.IO.Path]::GetFileNameWithoutExtension($file) $extension = [System.IO.Path]::GetExtension($file) $newName = "${now}_${nameFile}${extension}" Rename-Item -Path $file -NewName $newname Write-Host "$file renamed in $newname" $RenRegFile[$file] = $true } } # Crea un oggetto FileSystemWatcher per monitorare la cartella $watcher = New-Object System.IO.FileSystemWatcher $watcher.Path = $FolderToMonitor $watcher.Filter = "*.msg" $watcher.IncludeSubdirectories = $true $watcher.EnableRaisingEvents = $true # Associa l'azione all'evento Created e Renamed Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action while ($true) { # Azione da intraprendere quando viene rilevato un nuovo file $action = { $changeType = $Event.SourceEventArgs.ChangeType $file = $Event.SourceEventArgs.FullPath if ($changeType -eq "Created" -or $changeType -eq "Renamed") { Rename-FileMSG -file $file } } # Attendi che lo script venga interrotto Write-Host "Waiting for new MSG files..." Start-Sleep -Seconds 30 }This one does work:
# Cartella da monitorare (stessa cartella) $FolderToMonitor = "C:\TEST" # Crea un registro per i file già rinominati $RenRegFile = "C:\TEST\registro.txt" function Rename-FileMSG { param ( [string]$file ) Start-Transcript C:\test\script.log if ($file -match "\.msg$" -and -not $RenRegFile.Contains($file)) { $now = Get-Date -Format "yyyyMMddHHmm" $nameFile = [System.IO.Path]::GetFileNameWithoutExtension($file) $extension = [System.IO.Path]::GetExtension($file) $newName = "${now}_${nameFile}${extension}" Rename-Item -Path $file -NewName $newname Write-Host "$file renamed in $newname" $RenRegFile[$file] = $true } } # Crea un oggetto FileSystemWatcher per monitorare la cartella $watcher = New-Object System.IO.FileSystemWatcher $watcher.Path = $FolderToMonitor $watcher.Filter = "*.msg" $watcher.IncludeSubdirectories = $true $watcher.EnableRaisingEvents = $true # Associa l'azione all'evento Created e Renamed Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action while ($true) { # Azione da intraprendere quando viene rilevato un nuovo file $action = { $changeType = $Event.SourceEventArgs.ChangeType $file = $Event.SourceEventArgs.FullPath if ($changeType -eq "Created" -or $changeType -eq "Renamed") { Rename-FileMSG -file $file } } # Attendi che lo script venga interrotto Write-Host "Waiting for new MSG files..." Start-Sleep -Seconds 30 } - Turion986Sep 12, 2023Copper Contributor
Harm_Veenstra i added a pause in the middle of the code and now i have this error back
Exception setting "EnableRaisingEvents": "The path is not of a legal form." At C:\Users\Test\Desktop\Test - Copy.ps1:33 char:1 + $watcher.EnableRaisingEvents = $true + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], SetValueInvocationException + FullyQualifiedErrorId : ExceptionWhenSetting - Sep 11, 2023I'm running Windows 11 but tried in in PS5 and PS7...
- Turion986Sep 11, 2023Copper Contributor
Harm_Veenstra this is what i have with the script that for you works.....nothing back....
i cannot really understand waht i am doing wrong...
- Sep 08, 2023It works now because of that?