Monitor folder

I have a script that monitors a folder and it’s subfolders. It is used by the ftp server as a landing location for when we receive ftp files. The script sends an email to the recepients that a new file has been created in the folder. The script works, but It sends an email for every file that was copied to the location. I only want it to send 1 email to the recepients if a file was created in the last 6 hours. This way if they ftp more than 1 file in the last 6 hours, then only 1 email goes out. How can i modify my script to do this?

# make sure you adjust this to point to the folder you want to monitor

$PathToMonitor = “U:\FTPFolder\Test"

explorer $PathToMonitor

$FileSystemWatcher = New-Object System.IO.FileSystemWatcher

$FileSystemWatcher.Path  = $PathToMonitor

$FileSystemWatcher.IncludeSubdirectories = $true

# make sure the watcher emits events

$FileSystemWatcher.EnableRaisingEvents = $true

# define the code that should execute when a file change is detected

$Action = {

    $details = $event.SourceEventArgs

    $Name = $details.Name

    $FullPath = $details.FullPath

    $OldFullPath = $details.OldFullPath

    $OldName = $details.OldName

    $ChangeType = $details.ChangeType

    $Timestamp = $event.TimeGenerated

    $text = "{0} was {1} at {2}" -f $FullPath, $ChangeType, $Timestamp

    Write-Host ""

    Write-Host $text -ForegroundColor Green

    # you can also execute code based on change type here

    switch ($ChangeType)

    {

        'Changed' {

                    #$EmailFrom = “EmailAddress2@myemail.com”

                    #$EmailTo = “EmailAddress2@myemail.com, Person2@hotmail.com”

                    #$Subject = “New File FTP””

                    #$Body = $text

                    #$SMTPServer = “smtp.office365.com”

                    #$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)

                    #$SMTPClient.EnableSsl = $true

                    #$SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“EmailAddress1@myemail.com”, “Password”);

                    #$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

                    #Start-Sleep -Seconds 4

                    #$SMTPClient.Dispose()

                    # this executes only when a file was renamed

                    $text = "File {0} was Changed" -f $FullPath

                    Write-Host $text -ForegroundColor Yellow

                  }

        'Created' {

                    $EmailFrom = “EmailAddress2@ myemail.com”

                    $EmailTo = “EmailAddress2@myemail.com, Person2@hotmail.com”

                    $Subject = “New File FTP”

                    $Body = $text

                    $SMTPServer = “smtp.office365.com”

                    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)

                    $SMTPClient.EnableSsl = $true

                    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“EmailAddress1@myemail.com”, “Password”);

                    $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

                    Start-Sleep -Seconds 4

                    $SMTPClient.Dispose()

                    # this executes only when a file was renamed

                    $text = "File {0} was Created" -f $FullPath

                    Write-Host $text -ForegroundColor Yellow

                  }

        'Deleted' {

                    #$EmailFrom = “EmailAddress2@ myemail.com”

                    #$EmailTo = “EmailAddress2@myemail.com, Person2@hotmail.com”

                    #$Subject = “New File FTP”

                    #$Body = $text

                    #$SMTPServer = “smtp.office365.com”

                    #$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)

                    #$SMTPClient.EnableSsl = $true

                    #$SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“EmailAddress1@myemail.com”, “Password”);

                    #$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

                    #Start-Sleep -Seconds 4

                    #$SMTPClient.Dispose()

                    # this executes only when a file was renamed

                    $text = "File {0} was deleted" -f $FullPath

                    Write-Host $text -ForegroundColor Yellow

                    # uncomment the below to mimick a time intensive handler

                    <#

                    Write-Host "Deletion Handler Start" -ForegroundColor Gray

                    Start-Sleep -Seconds 4    

                    Write-Host "Deletion Handler End" -ForegroundColor Gray

                    #>

                  }

        'Renamed' {

                    #$EmailFrom = “EmailAddress2@ myemail.com”

                    #$EmailTo = “EmailAddress2@myemail.com, Person2@hotmail.com”

                    #$Subject = “New File FTP”

                    #$Body = $text

                    #$SMTPServer = “smtp.office365.com”

                    #$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)

                    #$SMTPClient.EnableSsl = $true

                    #$SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“EmailAddress1@myemail.com”, “Password”);

                    #$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

                    #Start-Sleep -Seconds 4

                    #$SMTPClient.Dispose()

                    # this executes only when a file was renamed

                    $text = "File {0} was renamed to {1}" -f $OldName, $Name

                    Write-Host $text -ForegroundColor Yellow

                  }

        default { Write-Host $_ -ForegroundColor Red -BackgroundColor White }

    }

}

# add event handlers

$handlers = . {

    Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Changed -Action $Action -SourceIdentifier FSChange

    Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Created -Action $Action -SourceIdentifier FSCreate

    Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Deleted -Action $Action -SourceIdentifier FSDelete

    Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Renamed -Action $Action -SourceIdentifier FSRename

}

Write-Host "Watching for changes to $PathToMonitor"

try

{

    do

    {

        Wait-Event -Timeout 1

        Write-Host "." -NoNewline

        

    } while ($true)

}

finally

{

    # this gets executed when user presses CTRL+C

    # remove the event handlers

    Unregister-Event -SourceIdentifier FSChange

    Unregister-Event -SourceIdentifier FSCreate

    Unregister-Event -SourceIdentifier FSDelete

    Unregister-Event -SourceIdentifier FSRename

    # remove background jobs

    $handlers | Remove-Job

    # remove filesystemwatcher

    $FileSystemWatcher.EnableRaisingEvents = $false

    $FileSystemWatcher.Dispose()

    "Event Handler disabled."

}

https://social.technet.microsoft.com/Forums/en-US/31699dc8-6270-47a9-8f0d-4271cb681ae9/monitor-changes-in-folder?forum=winserverpowershell#67510fa6-62af-4f93-841b-40c30ad0f304

The solution posted is made specifically for ‘real-time’, every 6 hours is actually more straight-forward. It looks like all of the emails are going to the same email thread? If you have different emails based on filenames or something to that effect, you can do something like this:

$files = Get-ChildItem -Path 'C:\Scripts\*temp*.txt' -File | 
         Select FullName, 
                LastWriteTime, 
                @{Name='Email';Expression={'{0}@myemail.com' -f ($_.BaseName -split '_')[0]}}

$grpFiles = $files | Group-Object -Property Email

foreach ($grp in $grpFiles) {
    $params = @{
        To = $grp.Name
        Subject = 'You have {0} FTP files' -f $grp.Count
        Body = ($grp.Group | ConvertTo-Html -Property FullName, LastWriteTime | Out-String)
        BodyAsHtml = $true
    }

    $params
    #Send-MailMessage @params
}

The files look like this:

PS C:\Users\rasim> $files

FullName                    LastWriteTime         Email            
--------                    -------------         -----            
C:\Scripts\amy_Temp1.txt    11/22/2019 4:25:10 PM amy@myemail.com  
C:\Scripts\amy_Temp2.txt    11/22/2019 4:25:10 PM amy@myemail.com  
C:\Scripts\amy_Temp5.txt    11/22/2019 4:25:10 PM amy@myemail.com  
C:\Scripts\amy_Temp8.txt    11/22/2019 4:25:10 PM amy@myemail.com  
C:\Scripts\john_Temp0.txt   11/25/2019 9:28:47 AM john@myemail.com 
C:\Scripts\john_Temp4.txt   11/22/2019 4:25:10 PM john@myemail.com 
C:\Scripts\john_Temp6.txt   11/22/2019 4:25:10 PM john@myemail.com 
C:\Scripts\john_Temp7.txt   11/22/2019 4:25:10 PM john@myemail.com 
C:\Scripts\sally_Temp10.txt 11/22/2019 4:25:11 PM sally@myemail.com
C:\Scripts\sue_Temp3.txt    11/22/2019 4:25:10 PM sue@myemail.com  
C:\Scripts\sue_Temp9.txt    11/22/2019 4:25:10 PM sue@myemail.com

The hours can be added or you can implement a process to move the files or flip an archive bit and then you are just getting all files that are not flipped which would work if the script errored out you could run it 15 hours later and it would just email all non-Archived files. The script could just be run as a scheduled task.

Rob, thanks for the examples…this is very helpful and gives me a good starting point. I will be sending an email to several people depending on the folder name, as each folder is for a different client. If the client uploads 10 files in the last 6 hours, then i want to send out only 1 email confirming that the files were ftp to the folder. I was using the filesystemwatcher to monitor any new files in the folders…but that was sending an email out for each file that was added to the folder.