wbrandle
asked on
How do I monitor a folder and email changes once a day?
I have three different folders I need to monitor on a server. One for new folders and files added, one for files removed or deleted, and the other directory for files that have changed or been modified. I need a separate email sent to specified email addresses for each directory once a day, at a specified time, and its content will list the folders and files that have been added, modified, or deleted. I have tried folder spy but it sends emails for every single change and that’s just too many emails. Would prefer a PowerShell script that I could run as a scheduled task but at this point anything that will work I am interested in. Can anyone help?
ASKER
Just a new list. Basically, what has changed since the last email was sent out. I need the task done automatically so it does not become another added daily task. The first directory is basically and "Inbox" for a specific group of employees to copy their completed work too. Then another specific group would get notified that there are files waiting for them so they could move the file out to another location.
The other two locations are just for monitoring sensitive restrictive directories.
The other two locations are just for monitoring sensitive restrictive directories.
I would go the "compare to snapshot" way. The only issue is that you need to create the first snapshot manually.
Alternatively, you can trust to the archive bit (but need to reset it after processing to make it work) for added or changed files.
For deleted files you'll always need a reference, if not using a trigger (file system watcher).
Alternatively, you can trust to the archive bit (but need to reset it after processing to make it work) for added or changed files.
For deleted files you'll always need a reference, if not using a trigger (file system watcher).
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
To do it with a "snapshot" file, I'd recommend loading those CSVs into datatables, then doing a compare there to generate the differences. This EE answer from another question shows how I'd do the datatable compares:
foreach ($row in $dt1.Rows)
{
$sqlRow = $dt2.Select("ID="+$row.ID)
if ($sqlRow.Length -ne 0)
{
Write-Host "Update action."
}
else
{
Write-Host "Insert action."
}
}
foreach ($row in $dt2.Rows)
{
$compareRow = $dt1.Select("ID="+$row.ID)
if ($compareRow.Length -eq 0)
{
Write-Host "Remove Action."
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
+1 for file system watcher.
https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
ASKER
That's a lot of information, I will experiment with provided input thus far and get back to you a little later. Thanks All.
ASKER
So to be up front, I am not a PowerShell guy so please bare with me.
So I tried Qlemo's first. I copied everything into PowerShell ISE. I created a folder on my C: drive called Monitoring with two subfolders Folder1 & Folder2. I changed the Smtp server information to an actual server and account. Rand the script and I get;
Compare-Object : Cannot bind argument to parameter 'ReferenceObject' because it is null.
At C:\Users\Employee\Document s\FolderMo nitor.ps1: 16 char:27
+ $cmp = compare-object $snapshot_old $snapshot_new
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Compare-Object], ParameterBindingValidation Except
ion
+ FullyQualifiedErrorId : ParameterArgumentValidatio nErrorNull NotAllowed ,Microsoft .PowerShel l
.Commands.CompareObjectCom mand
Compare-Object : Cannot bind argument to parameter 'ReferenceObject' because it is null.
At C:\Users\Employee\Document s\FolderMo nitor.ps1: 16 char:27
+ $cmp = compare-object $snapshot_old $snapshot_new
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Compare-Object], ParameterBindingValidation Except
ion
+ FullyQualifiedErrorId : ParameterArgumentValidatio nErrorNull NotAllowed ,Microsoft .PowerShel l
.Commands.CompareObjectCom mand
Was there something else I should have changed?
I will try Dustin's now. Thanks all.
So I tried Qlemo's first. I copied everything into PowerShell ISE. I created a folder on my C: drive called Monitoring with two subfolders Folder1 & Folder2. I changed the Smtp server information to an actual server and account. Rand the script and I get;
Compare-Object : Cannot bind argument to parameter 'ReferenceObject' because it is null.
At C:\Users\Employee\Document
+ $cmp = compare-object $snapshot_old $snapshot_new
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Compare-Object], ParameterBindingValidation
ion
+ FullyQualifiedErrorId : ParameterArgumentValidatio
.Commands.CompareObjectCom
Compare-Object : Cannot bind argument to parameter 'ReferenceObject' because it is null.
At C:\Users\Employee\Document
+ $cmp = compare-object $snapshot_old $snapshot_new
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Compare-Object], ParameterBindingValidation
ion
+ FullyQualifiedErrorId : ParameterArgumentValidatio
.Commands.CompareObjectCom
Was there something else I should have changed?
I will try Dustin's now. Thanks all.
The error message means that the snapshot file has been found, but was empty. And indeed, I forgot to create the initial file content :/.
$smtpParam = @{
SmtpServer = 'mail.domain.com'
from = 'me@domain.com'
to = 'you@domain.com'
}
foreach ($folder in 'C:\Monitoring\Folder1', 'C:\Monitoring\Folder2')
{
$del = $new = $chg = $null
$snapshot_file = 'C:\Monitoring\'+(split-path $folder -leaf)+'-files.txt'
$snapshot_new = Get-ChildItem -recurse $folder -Name
if (test-path $snapshot_file)
{
$snapshot_old = Get-Content $snapshot_file
$cmp = compare-object $snapshot_old $snapshot_new
$new = ($cmp | ? { $_.SideIndicator -eq '=>' }).InputObject
$del = ($cmp | ? { $_.SideIndicator -eq '<=' }).InputObject
$snapshot_date = (Get-ChildItem $snapshot_file).LastWriteTime
$chg = Get-ChildItem -recurse $folder | ? { $_.LastWriteTime -gt $snapshot_date } | Select -Expand Name
}
if ($new) { Send-MailMessage @smtpParam -Subject "$folder - new files" -Body ($new -join "`r`n") }
if ($del) { Send-MailMessage @smtpParam -Subject "$folder - deleted files" -Body ($del -join "`r`n") }
if ($chg) { Send-MailMessage @smtpParam -Subject "$folder - changed files" -Body ($chg -join "`r`n") }
$snapshot_new | Out-File $snapshot_file
}
ASKER
Qlemo, could you provide how I would change the first part to include port and authentication?
$smtpParam = @{
SmtpServer = 'mail.domain.com'
from = 'me@domain.com'
to = 'you@domain.com'
$smtpParam = @{
SmtpServer = 'mail.domain.com'
from = 'me@domain.com'
to = 'you@domain.com'
Authentication is usually not required if inside of your domain. It needs some more effort:
$smtpParam = @{
SmtpServer = 'mail.domain.com'
credential = New-Object System.Management.Automation.PsCredential('MyUser', (ConvertTo-SecureString 'MyPwd' -AsPlainText –force))
Port = 65432
from = 'me@domain.com'
to = 'you@domain.com'
}
You'll have to replace 'MyUser' and 'MyPwd', and of course the port number, by the real-life data.
Option 1 is to record all the files in the folder into a CSV or equivalent and then the scheduled task will compare what changed and send out an email. This doesn't require a running service, etc.
The other option is to create a file system watcher in a dummy service and have that record the changes.
Do you need to see every time the files change or just a list of new, deleted, changed files?