Solved

How do I monitor a folder and email changes once a day?

Posted on 2016-08-15
12
114 Views
Last Modified: 2016-08-23
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?
0
Comment
Question by:wbrandle
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 3
  • +1
12 Comments
 
LVL 13

Expert Comment

by:Dustin Saunders
ID: 41756647
You have 2 ways to do this, depending on how you want to go about it.

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?
1
 

Author Comment

by:wbrandle
ID: 41756662
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.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 41756674
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).
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 13

Assisted Solution

by:Dustin Saunders
Dustin Saunders earned 250 total points
ID: 41756676
The first approach I mentioned would look something like this (didn't get a chance to test it) but you'd need to compile this into a service with PowerGUI.  You can have functions fire when the file changes are done, so for example if a user makes a new file and it has the word 'invoice' in it, you get an email alert right away.  Otherwise it could just log the change and then send in the email later on.  It'd look like this:
$folder = 'c:\test\'
$filter = '*.*'
$logFolder = 'c:\log\'
$smtpServer = '192.168.1.1'
$smtpFrom = 'technotices@yourcompany.com'
$smtpTo = 'support@yourcompany.com'

$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 

function GetLogFile
{
    $date = Get-Date
    $logFile = $logFolder + $date.Month + "-" + $date.Day + "-fileChange.log"
    return $logFile
}

function RecordMessage ($message)
{
    $logFile = GetLogFile
    Add-Content -Path $logFile -Value $message
}

function SendLogEmail
{
    $logFile = GetLogFile
    $subject = "Log File for " + $date
    Send-MailMessage -SmtpServer $smtpServer -From $smtpFrom -To $smtpTo -Attachments $logFile -Subject $subject -Body "Log file attached."
}

Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
    $name = $folder + $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    $message = $name + " was " + $changeType + " at " + $timestamp + "."
    RecordMessage $message
} 

Register-ObjectEvent $fsw Deleted -SourceIdentifier FileDeleted -Action { 
    $name = $folder + $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    $message = $name + " was " + $changeType + " at " + $timestamp + "."
    RecordMessage $message
} 

Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action { 
    $name = $folder + $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    $message = $name + " was " + $changeType + " at " + $timestamp + "."
    RecordMessage $message
} 

while($true)
{
    $time = Get-Date
    if ($time.Hour -eq 23 -and $time.Minute -eq 59 -and $time.Second -eq 58) {SendLogEmail}
    Start-Sleep -Seconds 1
}

Open in new window

1
 
LVL 13

Expert Comment

by:Dustin Saunders
ID: 41756684
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."
    }
}

Open in new window

0
 
LVL 70

Accepted Solution

by:
Qlemo earned 250 total points
ID: 41756703
Assuming PowerShell 3.0 or above, a simplified approach is:
$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'
  if (test-path $snapshot_file)
  {
    $snapshot_old = Get-Content $snapshot_file
    $snapshot_new = Get-ChildItem -recurse $folder -Name
    $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
}

Open in new window

This treats all folders the same, and does not differ to whom mails are to send.
1
 
LVL 3

Expert Comment

by:Shabbir Rao
ID: 41756773
0
 

Author Comment

by:wbrandle
ID: 41756784
That's a lot of information, I will experiment with provided input thus far and get back to you a little later. Thanks All.
0
 

Author Comment

by:wbrandle
ID: 41757063
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\Documents\FolderMonitor.ps1:16 char:27
+     $cmp = compare-object $snapshot_old $snapshot_new
+                           ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Compare-Object], ParameterBindingValidationExcept
   ion
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell
   .Commands.CompareObjectCommand
 
Compare-Object : Cannot bind argument to parameter 'ReferenceObject' because it is null.
At C:\Users\Employee\Documents\FolderMonitor.ps1:16 char:27
+     $cmp = compare-object $snapshot_old $snapshot_new
+                           ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Compare-Object], ParameterBindingValidationExcept
   ion
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell
   .Commands.CompareObjectCommand

Was there something else I should have changed?

I will try Dustin's now. Thanks all.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 41757675
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
}

Open in new window

1
 

Author Comment

by:wbrandle
ID: 41758203
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'
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 41759815
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'
}

Open in new window

You'll have to replace 'MyUser' and 'MyPwd', and of course the port number, by the real-life data.
0

Featured Post

Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We asked our MSP customer base what their favorite tools were and how they help them serve clients. We focused our questions on favorite tools in the following categories: >PSA tools >RMM tools >Alert management tools >Communication tools and Mo…
Popular third-party chat platforms like Slack, Discord, and Telegram are just a few of the many new productivity applications that are being hijacked by cybercriminals to create command-and-control (C&C) communications infrastructures for their malw…
This tutorial will walk an individual through the process of configuring basic necessities in order to use the 2010 version of Data Protection Manager. These include storage, agents, and protection jobs. Launch Data Protection Manager from the deskt…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question