Obtain file name from FindFirstChangeNotification

How can I determine the file name used when using the FindFirstChangeNotification API function? I'm able to detect that a file has been written, but I don't know how to return the file name???
kaimAsked:
Who is Participating?
 
watyConnect With a Mentor Commented:
Use this class and module :

CNotify.cls
Option Explicit

Private Sub Class_Initialize()
    ' Count this object
    cObject = cObject + 1
    ' Initialize static data only once
    If ahNotify(0) <> 0 Then Exit Sub
    Dim i As Integer
    For i = 0 To cLastNotify
        ahNotify(i) = INVALID_HANDLE_VALUE
    Next
    aerr(errInvalidDirectory) = "Invalid directory"
    aerr(errInvalidType) = "Invalid notification type"
    aerr(errInvalidArgument) = "Invalid argument"
    aerr(errTooManyNotifications) = "Too many notifications"
    aerr(errNotificationNotFound) = "Notification not found"
End Sub

Private Sub Class_Terminate()
    ' Uncount this object
    cObject = cObject - 1
    ' Main loop tests -1 because count is 0 to start
    If cObject = 0 Then cObject = -1
End Sub

''@B Connect
Function Connect(objTarget As Object, sDir As String, _
                ordType As Long, fSubTree As Boolean) As Long
    Connect = INVALID_HANDLE_VALUE ' Assume fail
    Dim i As Long, h As Long
    ' Find blank handle space
    For i = 0 To cLastNotify
        If ahNotify(i) = INVALID_HANDLE_VALUE Then
            ' Set up notification
            h = FindFirstChangeNotification(sDir, fSubTree, ordType)
            Connect = h
            If h = INVALID_HANDLE_VALUE Then
                ' Change notification unsupported on remote disks
                If Err.LastDllError <> ERROR_NOT_SUPPORTED Then
                    RaiseError errInvalidArgument
                End If
                Exit Function
            End If
            ' Store information
            ahNotify(i) = h
            With aconNotify(i)
                Set .objTarget = objTarget
                .sDir = sDir
                .ordType = ordType
                .fSubTree = fSubTree
            End With
            Exit Function
        End If
    Next
    RaiseError errTooManyNotifications
End Function
''@E Connect

''@B Disconnect
Function Disconnect(hNotify As Long) As Boolean
    Dim i As Long, f As Boolean
    For i = 0 To cLastNotify
        If ahNotify(i) = hNotify Then
            ' Destroy notification
            f = FindCloseChangeNotification(hNotify)
            Disconnect = True
            ' Compact the arrays
            Do While i <= cLastNotify
                If ahNotify(i) = INVALID_HANDLE_VALUE Then Exit Do
                ahNotify(i) = ahNotify(i + 1)
                With aconNotify(i)
                    Set .objTarget = aconNotify(i + 1).objTarget
                    .sDir = aconNotify(i + 1).sDir
                    .ordType = aconNotify(i + 1).ordType
                    .fSubTree = aconNotify(i + 1).fSubTree
                End With
                i = i + 1
            Loop
            Exit Function
        End If
    Next
    RaiseError errNotificationNotFound
End Function
''@E Disconnect
'

-------------------------------------------------
NotifyError.bas

Option Explicit

Public Const errFirst = 100
Public Const errInvalidDirectory = 100
Public Const errInvalidType = 101
Public Const errInvalidArgument = 102
Public Const errTooManyNotifications = 103
Public Const errNotificationNotFound = 104
Public Const errNoFileChangeMethod = 105
Public Const errLast = 105

-------------------------------------------------
Notify.bas

Option Explicit

''@B Data
Public Type TConnection
    sDir As String
    ordType As Long
    fSubTree As Boolean
    objTarget As Object
End Type

' Actually cLastNotify + 1 allowed
Public Const cLastNotify = 28
' One extra blank item in each array for easy compacting
Public ahNotify(0 To cLastNotify + 1) As Long
Public aconNotify(0 To cLastNotify + 1) As TConnection
Public aerr(errFirst To errLast) As String
' Count of connected objects managed by class
Public cObject As Long
''@E Data


''@B Main
Sub Main()
    Dim iStatus As Long, f As Boolean, objTarget As Object
    ' Keep waiting for file change events until no more objects
    Do
        '  Wait 100 milliseconds for notification
        iStatus = WaitForMultipleObjects(Count, ahNotify(0), _
                                         False, 100)
        Select Case iStatus
        Case WAIT_TIMEOUT
            ' Nothing happened
            DoEvents
        Case 0 To Count
            ' Call client object with information
            On Error Resume Next
            With aconNotify(iStatus)
                .objTarget.FileChange .sDir, .ordType, .fSubTree
            End With
            If Err <> 0 Then RaiseError errNoFileChangeMethod
            On Error GoTo 0
            ' Wait for next notification
            f = FindNextChangeNotification(ahNotify(iStatus))
        Case WAIT_FAILED
            ' Indicates no notification requests
            DoEvents
        Case Else
            Debug.Print "Can't happen"
        End Select
    ' Class Initialize and Terminate events keep reference count
    Loop Until cObject = -1
End Sub
''@E Main

Private Property Get Count() As Long
    Dim i As Long
    For i = 0 To cLastNotify
        If ahNotify(i) = INVALID_HANDLE_VALUE Then Exit For
    Next
    Count = i
End Property

Public Sub RaiseError(iErr As Integer)
    Err.Raise vbObjectError + iErr, "FileNotify.CFileNotify", aerr(iErr)
End Sub
   




0
 
kaimAuthor Commented:
Adjusted points to 200
0
 
kaimAuthor Commented:
Very impressive!!! Much more thorough than I had expected.

There seems to be a few things omitted, ie., the API's (WaitForMultipleObjects), where the file names are returned? How sDir is defined?

I haven't thoroughly gone through it yet, I just copied and pasted it and watched it stare back at me.

Thanks though, slick stuff.

-k
0
 
watyCommented:
Here is a sample of use :

With notify
    filPic.Path = dirPic.Path
    If filPic.ListCount > 0 Then
        filPic.ListIndex = 0
    End If

    ' Watch whole drive for directory changes
    If hNotifyDir <> -1 Then .Disconnect hNotifyDir
    hNotifyDir = .Connect(Me, dirPic.Path, _
                          FILE_NOTIFY_CHANGE_DIR_NAME, False)
    ' Watch only current directory for file changes
    If hNotifyFile <> -1 Then .Disconnect hNotifyFile
    hNotifyFile = .Connect(Me, dirPic.Path, _
                           FILE_NOTIFY_CHANGE_FILE_NAME, False)
    ' Watch only current directory for file modifications
    If hNotifyChange <> -1 Then notify.Disconnect hNotifyChange
    hNotifyChange = .Connect(Me, dirPic.Path, _
                             FILE_NOTIFY_CHANGE_LAST_WRITE, False)
End With

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.