Link to home
Start Free TrialLog in
Avatar of Kevin
KevinFlag for United States of America

asked on

VB.net Filesystem watcher not working

Good Afternoon,

I can't seem to get my FileSystemWatcher to work. I want it to display the results of the watch folder in a list box. But when I copy a file to the watched directory no data is written to the list box control. Please note that I am not getting any errors.

Kindly advise if I am missing something.

Code is below.

Public Class frmConfigurations

    'Connection Variables
    Dim conn As SqlConnection
    Dim connectionString = SQLConnString()
    Dim sql As String

    'WatchFolder Variables
    Public watchfolder As FileSystemWatcher
    Public str As String = ""

Open in new window


Private Sub frmConfigurations_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        Try

            conn = New SqlConnection(connectionString)
            conn.Open()

            sql = "SELECT ID, ClientNumber, OfficerName, OfficerEmail, AssistantName, AssistantEmail FROM Contacts ORDER BY ClientNumber"

            Dim dscmd As New SqlDataAdapter(sql, conn)
            dscmd.SelectCommand.CommandTimeout = 60

            Dim ds As New DataSet
            dscmd.Fill(ds)

            dgvData.DataSource = ds.Tables(0)

        Catch ex As Exception
            MsgBox(ErrorToString)

        Finally
            conn.Close()

        End Try

        'Set the Monitoring Directory
        txtWatchPath.Text = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\GlobusMailWatch"

        'Create the monitoring directory if it does not exist already
        If Not Directory.Exists(txtWatchPath.Text) Then
            Directory.CreateDirectory(txtWatchPath.Text)
        End If   

Open in new window


Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click

        btnStart.Enabled = False
        btnStop.Enabled = True
        txtMonStatus.Text = "Started"

        'Prepare to handle the monitoring folder
        subInitializeWatchFolder()

    End Sub

Open in new window


Private Sub subInitializeWatchFolder()

        watchfolder = New FileSystemWatcher

        'This is the path we are monitoing
        watchfolder.Path = txtWatchPath.Text

        'Watch for changes
        watchfolder.NotifyFilter = NotifyFilters.CreationTime

        'Only watch for .MSG files
        watchfolder.Filter = "*.msg"

        'Event Handlers
        AddHandler watchfolder.Created, AddressOf logCreated
        AddHandler watchfolder.Deleted, AddressOf logDeleted

        'Start monitoring folder
        watchfolder.EnableRaisingEvents = True

    End Sub

Open in new window


Private Sub logCreated(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)

        str = e.FullPath

        lsbxLog.Items.Add("CREATED: " & str)

    End Sub

    Private Sub logDeleted(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)

        str = e.FullPath

        lsbxLog.Items.Add("DELETED: " & str)

    End Sub

Open in new window

Avatar of Éric Moreau
Éric Moreau
Flag of Canada image

have you tried to handle the .Changed event? Have a look at http://emoreau.com/Entries/Articles/2005/04/The-FileSystemWatcher-component.aspx
I think you might be trying to do something like this:
Form1.vb -
Imports System.ComponentModel
Imports System.IO
Imports System.Threading

Public Class Form1
    Private isRunning = False
    Private lastChangedTime As DateTime = DateTime.Now
    Private lastFilePath As String = String.Empty
    Private ReadOnly QueuedFiles As New List(Of ProcessableFile)
    WithEvents watchfolder As FileSystemWatcher
    WithEvents worker As New BackgroundWorker With {.WorkerReportsProgress = True, .WorkerSupportsCancellation = True}

    Private Sub OnLoad(sender As Object, e As EventArgs) Handles MyBase.Load
        'Create the monitoring directory if it does not exist already
        If Not Directory.Exists(Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "GlobusMailWatch")) Then
            Directory.CreateDirectory(Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "GlobusMailWatch"))
        End If
        isRunning = True
        worker.RunWorkerAsync()
        InitializeWatchFolder(Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "GlobusMailWatch"))
    End Sub

    Private Sub InitializeWatchFolder(path As String)
        watchfolder = New FileSystemWatcher(path, "*.msg") With {.EnableRaisingEvents = True}
    End Sub

    Private Sub LogAction(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs) Handles watchfolder.Created, watchfolder.Deleted, watchfolder.Changed
        Try
            Dim span = DateTime.Now.Subtract(lastChangedTime)
            If isRunning AndAlso span.TotalSeconds > 2 OrElse lastFilePath <> e.FullPath Then
                ' Wait a second for any locks to be released before taking actions
                Thread.Sleep(1000)
                Select Case e.ChangeType
                    Case WatcherChangeTypes.Created
                        lastChangedTime = DateTime.Now
                        lastFilePath = e.FullPath
                        Dim match = (From pFile In QueuedFiles Where pFile.File.FullName.Equals(e.FullPath, StringComparison.OrdinalIgnoreCase) Select pFile).SingleOrDefault()
                        If match Is Nothing Then
                            SyncLock (QueuedFiles)
                                QueuedFiles.Add(New ProcessableFile(New FileInfo(e.FullPath)))
                            End SyncLock
                        End If
                        Exit Select
                    Case WatcherChangeTypes.Deleted
                        lastChangedTime = DateTime.Now
                        lastFilePath = e.FullPath
                        Dim match = (From pFile In QueuedFiles Where pFile.File.FullName.Equals(e.FullPath, StringComparison.OrdinalIgnoreCase) Select pFile).SingleOrDefault()
                        If match IsNot Nothing Then
                            SyncLock (QueuedFiles)
                                QueuedFiles.Remove(match)
                            End SyncLock
                        End If
                        Exit Select
                End Select
                worker.ReportProgress(0, String.Format("{0}: {1}", e.ChangeType.ToString().ToUpper(), e.FullPath))
            End If
        Catch ex As Exception
            Console.WriteLine("Exception reported - {0}", ex)
        End Try
    End Sub

    Private Sub OnDoWork(sender As Object, e As DoWorkEventArgs) Handles worker.DoWork
        Try
            While (isRunning)
                SyncLock (QueuedFiles)
                    For i As Integer = QueuedFiles.Count - 1 To 0 Step -1
                        If Not QueuedFiles(i).IsProcessing Then
                            'Simulating a long process
                            Thread.Sleep(10000)
                            Console.WriteLine("Processing new item - {0}", QueuedFiles(i).File.FullName)
                            QueuedFiles(i).IsProcessing = True
                        Else
                            If Not QueuedFiles(i).IsProcessed Then
                                Console.WriteLine("Finished processing - {0}", QueuedFiles(i).File.FullName)
                                QueuedFiles(i).IsProcessed = True
                            Else
                                QueuedFiles(i).File.Delete()
                            End If
                        End If
                    Next
                End SyncLock
            End While
        Catch ex As Exception

        End Try
    End Sub

    Private Sub OnProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles worker.ProgressChanged
        ListBox1.Items.Add(CType(e.UserState, String))
    End Sub

    Private Sub OnClosing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        isRunning = False
        worker.CancelAsync()
    End Sub
End Class

Class ProcessableFile
    Private ReadOnly fFile As FileInfo
    Public ReadOnly Property File() As FileInfo
        Get
            Return fFile
        End Get
    End Property

    Public Property IsProcessing() As Boolean
    Public Property IsProcessed() As Boolean

    Public Sub New(ByVal [file] As FileInfo)
        fFile = file
    End Sub
End Class

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.ListBox1 = New System.Windows.Forms.ListBox()
        Me.SuspendLayout()
        '
        'ListBox1
        '
        Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ListBox1.FormattingEnabled = True
        Me.ListBox1.Location = New System.Drawing.Point(0, 0)
        Me.ListBox1.Name = "ListBox1"
        Me.ListBox1.Size = New System.Drawing.Size(707, 261)
        Me.ListBox1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(707, 261)
        Me.Controls.Add(Me.ListBox1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

    Friend WithEvents ListBox1 As ListBox
End Class

Open in new window

Which produces the following output -User generated image
-saige-
Avatar of Kevin

ASKER

Good Afternoon,

@Eric, Yes I have tried to hand the .Changed event, but its the same result when I attempt. Nothing appears in the listbox control and I receive no errors.

@it_saige, thank you for taking the time to write all that code. While it does work I feel a little overwhelmed as I don't understand a lot of it. I'm still quite the beginner. So I don't feel comfortable incorporating it in to my project as if something needs changing I won't know where to proceed with my current skill set.

Are you able to look at my current code and advise if something is missing or not correct?

Kindly advise.

Regards,
N
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Kevin

ASKER

Thank you very much for your assistance it_saige.