WMI Eventing: Watch folder and send files as email attachments, Part I

I got a question from one of my colleagues if I knew an application that watched a folder for files, and then emailed all files to a specific address. My immediate answer was that this can very easily be achieved with PowerShell.

Short version

First we define the action to trigger when a file is found. We simply enumerate all files with Get-ChildItem and then use the standard Send-MailMessage cmdlet to send them to the recipient.

WatchFolder2Email.ps1

$WatchFolder = "C:\Data"
$To = "admin@365lab.net"
$From = "noreply@365lab.net"
$Subject = "File transfer"
$Body = "Please check the attached file(s)."
$SMTPServer = "smtp.cloud.net"
 
$Files = (Get-ChildItem $WatchFolder).FullName
if ($Files) {
    Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Files
    Remove-Item $Files
}

Now we could call our problem solved. Just put the code in a .ps1 file and use Task Scheduler to run it every 10 minutes.

Advanced version

Another way of triggering the script is to use WMI Eventing. There are different types of events, I will use an intrinsic event which are events triggered on a change to the CIM database, for example a change in the file system. This is defined in a WQL Query that also defines an interval and which folder to watch.

SELECT * FROM __InstanceCreationEvent WITHIN 10 
WHERE TargetInstance ISA "CIM_DirectoryContainsFile" 
AND TargetInstance.GroupComponent = "Win32_Directory.Name=\"c:\\\\Data\""

Let’s put the script together and register the event.

$action = {
    $WatchFolder = "C:\Data"
    $To = "admin@365lab.net"
    $From = "noreply@365lab.net"
    $Subject = "File transfer"
    $Body = "Please check the attached file(s)."
    $SMTPServer = "smtp.cloud.net"
        
    $Files = (Get-ChildItem $WatchFolder).FullName 
    if ($Files) {
        Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Attachments $Files 
        Remove-Item $Files
    }
}

$WQLQuery = 'SELECT * FROM __InstanceCreationEvent WITHIN 10 
             WHERE TargetInstance ISA "CIM_DirectoryContainsFile"
             AND TargetInstance.GroupComponent = "Win32_Directory.Name=\"c:\\\\Data\""'

Register-WmiEvent -Query $WQLQuery -SourceIdentifier "WatchFolder2Email" -Action $action  

Now we can put a file in the C:\Data folder. Within seconds it will be sent by email and then deleted.

To remove the Job we simply run

Unregister-Event -SourceIdentifier "WatchFolder2Email" 

Unfortunately this solution is limited to your PowerShell session only. When you close the window the job is terminated. In Part II of this blog post I will show how to create a Permanent WMI Consumer that will work also after computer restarts.

/ Andreas

Advertisements

3 thoughts on “WMI Eventing: Watch folder and send files as email attachments, Part I

  1. Björn Willim

    Nice simple solution on a common problem. I realy liked the advanced with wmi eventing. 🙂

  2. siqi

    Hi, I have been trying to find ways to watch new files added to a shared drive. Is it possible to do so using WMI?

    1. Andreas Lindahl Post author

      In order to do that you have to use WMI on the server hosting the file share.

Comments are closed.