The use of .NET classes can extend Posh capabilities.
In the present user case, I will use the System.IO.FileSystemWatcher
.NET Class.
$Watcher = [System.IO.FileSystemWatcher]::new()
Or another classic way
$Watcher = New-Object System.IO.FileSystemWatcher
Now, let's examine the $Watcher variable and properties
$Watcher | get-member
TypeName : System.IO.FileSystemWatcher
Name MemberType Definition
---- ---------- ----------
Changed Event System.IO.FileSystemEventHandler Changed(System.Object, System.IO.FileSystemEventArgs)
Created Event System.IO.FileSystemEventHandler Created(System.Object, System.IO.FileSystemEventArgs)
Deleted Event System.IO.FileSystemEventHandler Deleted(System.Object, System.IO.FileSystemEventArgs)
Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs)
Error Event System.IO.ErrorEventHandler Error(System.Object, System.IO.ErrorEventArgs)
Renamed Event System.IO.RenamedEventHandler Renamed(System.Object, System.IO.RenamedEventArgs)
BeginInit Method void BeginInit(), void ISupportInitialize.BeginInit()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose Method void Dispose(), void IDisposable.Dispose()
EndInit Method void EndInit(), void ISupportInitialize.EndInit()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
ToString Method string ToString()
WaitForChanged Method System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType), System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes cha...
Container Property System.ComponentModel.IContainer Container {get;}
EnableRaisingEvents Property bool EnableRaisingEvents {get;set;}
Filter Property string Filter {get;set;}
IncludeSubdirectories Property bool IncludeSubdirectories {get;set;}
InternalBufferSize Property int InternalBufferSize {get;set;}
NotifyFilter Property System.IO.NotifyFilters NotifyFilter {get;set;}
Path Property string Path {get;set;}
Site Property System.ComponentModel.ISite Site {get;set;}
SynchronizingObject Property System.ComponentModel.ISynchronizeInvoke SynchronizingObject {get;set;}
As we can see, the Property NotifyFilter
is a System.IO.NotifyFilters
.NET class
Deep dive in this class
[System.IO.NotifyFilters]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True NotifyFilters System.Enum
This is a System.Enum
BaseType
[System.IO.NotifyFilters].BaseType
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Enum System.ValueType
and by using the Enum
type, we can view the values of System.IO.NotifyFilters
using the GetNames
Method
[Enum]::GetNames('System.IO.NotifyFilters')
FileName
DirectoryName
Attributes
Size
LastWrite
LastAccess
CreationTime
Security
Then we can use one, or more of these values to define our NotifyFilter
property
The other properties are simple to understand by themselves.
# Path to Input Folder
$InputFolder = "\\path\to\folder"
# filter to apply according to your requirements
$filter = '*.*'
$Watcher.Path = $InputFolder # Input Folder to watch
$Watcher.Filter = $Filter # Filter to apply (i.e. "*.", "*.jpg")
$Watcher.IncludeSubdirectories = $true # Define if Watching only root folder or subfolders too
$Watcher.EnableRaisingEvents = $true # Boolean value to indicate enablement of the watcher. To be able to subscribe to the events generated by .NET Framework objects
$Watcher.NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' # Define NotifyFilter to apply.
We can review and Display Watcher properties
$Watcher
NotifyFilter : FileName, LastWrite
EnableRaisingEvents : True
Filter : *.*
IncludeSubdirectories : True
InternalBufferSize : 8192
Path :
Site :
SynchronizingObject :
Container :
$Action = {
$Path = $Event.SourceEventArgs.FullPath
$Name = $Event.SourceEventArgs.Name
$ChangeType = $Event.SourceEventArgs.ChangeType
$TimeStamp = $Event.TimeGenerated
# Add all actions to do. See the following example
# Move-Item $Path -Destination $Backup -Force -Verbose # Force will overwrite files with same name
#$LogLine = "$(Get-Date), $ChangeType, $Path" # Define content for log
# Add-content -Path $LogFile -value $LogLine # add to log file (already existing)
}
$OnCreated = Register-ObjectEvent -InputObject $Watcher -EventName Created -SourceIdentifier FileCreated -Action $Action
At this step all events are monitored by the watcher. To stop the watcher, use
Unregister-Event -SourceIdentifier FileCreated
$Watcher = [System.IO.FileSystemWatcher]::new()
# Path to Input Folder
$InputFolder = "C:\temp"
# Path to Backup Folder
$Backup = "C:\temp2"
# Path Log File
$LogFile = "c:\temp3\log.txt"
# filter to apply
$filter = '*.*'
$Watcher.Path = $InputFolder # Input Folder to watch
$Watcher.Filter = $Filter # Filter to apply (i.e. "*.", "*.jpg")
$Watcher.IncludeSubdirectories = $true # Define if Watching only root folder or subfolders too
$Watcher.EnableRaisingEvents = $true # Boolean value to indicate enablement of the watcher. To be able to subscribe to the events generated by .NET Framework objects
$Watcher.NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' # Define NotifyFilter to apply.
$Action = {
$Path = $Event.SourceEventArgs.FullPath
$Name = $Event.SourceEventArgs.Name
$ChangeType = $Event.SourceEventArgs.ChangeType
$TimeStamp = $Event.TimeGenerated
Move-Item $Path -Destination $Backup -Force -Verbose # Force will overwrite files with same name
$LogLine = "$(Get-Date), $ChangeType, $Path" # Define content for log
Add-content -Path $LogFile -value $LogLine # add to log file (already existing)
Write-Output " Moving action added to $LogFile"
}
$OnCreated = Register-ObjectEvent -InputObject $Watcher -EventName Created -SourceIdentifier FileCreated -Action $Action
New-Item -Path c:\temp\NewtestFile.txt
Répertoire : C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/02/2020 13:53 0 NewtestFile.txt
COMMENTAIRES : Opération « Déplacer le fichier » en cours sur la cible « Élément : C:\temp\NewtestFile.txt Destination : C:\temp2\NewtestFile.txt ».
Get-Content C:\Temp3\Log.txt
02/12/2020 13:52:14, Created, C:\temp\Nouveau Microsoft Excel Worksheet.xlsx
02/12/2020 13:52:14, Created, C:\temp\~ouveau Microsoft Excel Worksheet.tmp
02/12/2020 13:52:15, Created, C:\temp\Nouveau Microsoft Excel Worksheet.xlsx~RF3bf2bda.TMP
02/12/2020 13:53:54, Created, C:\temp\NewtestFile.txt
Unregister-Event -SourceIdentifier FileCreated
The module unfortunately is not available in the PowerShell Gallery, but the creator's GitHub page does provide an installation PowerShell script that will create the module on a local machine.
You can see the Github site at this link : https://github.com/jfromaniello/pswatch, download or install it, or use the Install.ps1 file on the site to install or import the Module.
[Nota] The module contains only one function call watch with Only few parameters : [String]$location = "", [switch]$includeSubdirectories = $true, [switch]$includeChanged = $true, [switch]$includeRenamed = $true, [switch]$includeCreated = $true, [switch]$includeDeleted = $false
Let's use it with a sample
Import-module -Name PSWatch # previously think to unblock files if you have manually download Module files
watch -location c:\temp -includeSubdirectories -includeRenamed | foreach { Write-Output "Change made on $($_.Path)"}
Change made on c:\temp\ScheduledTasks.log
# You can also use simultaneously all parameters
watch -location c:\temp -includeSubdirectories -includeRenamed -includeChanged -includeCreated -includeDeleted | foreach { Write-Output "Change made on $($_.Path)"}
Change made on c:\temp\ScheduledTasks.log
[Nota 2] At this step the watcher is still alive
As a function, this could be use in a .ps1 script file.
Other use from the Github site :
Import-Module pswatch
watch "Myfolder\Other" |
Foreach-Object {
Write-Host "$_.Path has changed!"
RunUnitTests.exe $_.Path
}
You can filter by using powershell pipelining as follows:
watch | Get-Item |
Where-Object { $_.Extension -eq ".js" } |
Foreach-Object {
do the magic...
}
This post was build based on informations found on the following
https://docs.microsoft.com/fr-fr/dotnet/api/system.io.filesystemwatcher?view=netframework-4.8 https://stackoverflow.com/questions/31795933/powershell-and-system-io-filesystemwatcher https://github.com/jfromaniello/pswatch https://4sysops.com/archives/monitor-file-changes-in-windows-with-powershell-and-pswatch/ https://4sysops.com/archives/the-system-io-filesystemwatcher-net-class-raise-file-system-notifications-in-powershell/ https://www.nextofwindows.com/how-to-monitor-a-folder-for-changes-the-easy-way
Hope this helpful