In our environment, large numbers of users are working on a daily basis and it very difficult to track what file they have modified and which time. To handle this scenario, my team was requested to monitor a directory for any file changes and receive alerts of those changes when they trying to update/Delete/renamed/created in a specific location inside the service and this requirement made me create this post. In this post, we will discuss how to monitor changes in the folder including sub-files, and log in to the log text file.
STEP #1
To monitor a folder for new files in Windows with PowerShell, we can use a .NET class called FileSystemWatcher. This class is in the System.IO namespace and can be created with the New-Object cmdlet.
$filewatcher = New-Object System.IO.FileSystemWatcher
STEP #2
To monitoring a folder/all sub-folders we need to assign the IncludeSubdirectories property as true.
$filewatcher.IncludeSubdirectories = $true
STEP #3
Then you need to specify which folder you I’ll be monitoring and also set the EnableRaisingEvents property to $true. The component is set to watch for changes in the last write and last access time, the creation, deletion, or renaming of text files in the directory. It will not raise events unless you set EnableRaisingEvents to true.
$filewatcher.EnableRaisingEvents = $true
STEP #4
In below code we using built-in [$event] variable. This is a variable that will be present every time an event fires and contains information such as the file path and the type of event that fired. In this script block, we capturing all the events in the FileWatcher_log.txt while event is fired.
$writeaction = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = “$(Get-Date), $changeType, $path”
Add-content “C:\D_EMS Drive\Personal\LBLOG\FileWatcher_log.txt” -value $logline
}
STEP #5
Finally, we need to register for the events. To perform this you need to use the Register-ObjectEvent cmdlet and need to supply it the watcher object we created and type of action to monitor like “Created”,”Changed”,”Deleted”,”Renamed”. The Register-ObjectEvent cmdlet subscribes to events that are generated by .NET objects on the local computer or on a remote computer.
Register-ObjectEvent $filewatcher “Created” -Action $writeaction
Register-ObjectEvent $filewatcher “Changed” -Action $writeaction
Register-ObjectEvent $filewatcher “Deleted” -Action $writeaction
Register-ObjectEvent $filewatcher “Renamed” -Action $writeaction
After executing the script, it will start to monitor the folder and sub-items from the given path and log the details in the FileWatcher_log.txt file.
Full Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO $filewatcher = New-Object System.IO.FileSystemWatcher #Mention the folder to monitor $filewatcher.Path = "C:\D_EMS Drive\Personal\LBLOG\" $filewatcher.Filter = "*.*" #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 $logline = "$(Get-Date), $changeType, $path" Add-content "C:\D_EMS Drive\Personal\LBLOG\FileWatcher_log.txt" -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 "Deleted" -Action $writeaction Register-ObjectEvent $filewatcher "Renamed" -Action $writeaction while ($true) {sleep 5} |
OUTPUT:
What do you think?
I hope you have an idea ofย Monitoring a Folder Using PowerShell Scripting with Powershell. I would like to have feedback from the readers of my post. Your valuable feedback, question, or comments about this article are always welcome.
The script only generates one entry but every time you execute it a new event is registered. Execute Get-EventSubscriber to get the list of events. Delete the events using Unregister-Event
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/unregister-event?view=powershell-7.3
Nice script!
I am also having issues with it writing multiple lines for some reason. I deleted one folder but i prints it twice in the log and I can’t figure out why. This is how I modified it.
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$filewatcher = New-Object System.IO.FileSystemWatcher
#Mention the folder to monitor
$filewatcher.Path = “X:\”
$filewatcher.Filter = “*.*”
#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
$logline = “$(Get-Date), $changeType, $path”
Add-content “C:\scripts\filewatcher\fileWatcher_log.txt” -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 “Deleted” -Action $writeaction
#Register-ObjectEvent $filewatcher “Renamed” -Action $writeaction
while ($true) {sleep 5}
Hi, checking on this, will update you ASAP.
Hi there
Thank you for your script. unfortunately the script is writing multiple lines to log file on 1 folder creation. See below
01/07/2022 11:16:49, Created, \\servername\data01\New folder, domain\username
01/07/2022 11:16:49, Created, \\servername\data01\New folder, domain\username
01/07/2022 11:16:49, Created, \\servername\data01\New folder, domain\username
01/07/2022 11:16:49, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:54, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:54, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:54, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:54, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:59, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:59, Changed, \\servername\data01\New folder, domain\username
01/07/2022 11:16:59, Renamed, \\servername\data01\HappyClappy, domain\username
01/07/2022 11:16:59, Renamed, \\servername\data01\HappyClappy, domain\username
01/07/2022 11:17:04, Renamed, \\servername\data01\HappyClappy, domain\username
It creates 3-4 lines for “created”, “changed”,”Renamed”,”Deleted” each. How can i Limit it to 1 line at a time?
Thanks in advance for your help
Hi there, thank you for your script. I intend on using it in my envionment but everytime i right click on the directory i am monitoring and select new folder, then set name of new folder….and press enter. I go to the log file and it just shows eg: \\servername\\New Folder (new folder) is what is logged in log file…not the new name i gave the folder eg: \\servername\\space (“new folder” renamed to “space” AT FOLDER CREATION)
Also it logs three to four lines in log per folder created or deletion etc
How can i fix?
I’m relatively new to PowerShell, and I’m curious about the while loop in the PS script. What code is being executed during the while loop? If I’m making a connection to a remote server, where I map a drive prior to running the File System Watcher would that could be also looped through?
Thank you for the clarification
dm
Hi,
You can get the logged-in user name using the below script and you can update same in log.
Another Method you can use $env:UserName to get the logged-in username and append in the log file
The output will be similar to Dir\XXXXXX
Thanks
thiyagu S
how can i know who changed or deleted the file ?
Easiest way to keep it running on background is by creating endless loop and using task scheduler.