Obtain file name from FindFirstChangeNotification

Posted on 1998-08-19
Medium Priority
Last Modified: 2008-03-17
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???
Question by:kaim
  • 2
  • 2

Author Comment

ID: 1429897
Adjusted points to 200
LVL 14

Accepted Solution

waty earned 800 total points
ID: 1429898
Use this class and module :

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
    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
    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
            Exit Function
        End If
    RaiseError errNotificationNotFound
End Function
''@E Disconnect


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


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
        '  Wait 100 milliseconds for notification
        iStatus = WaitForMultipleObjects(Count, ahNotify(0), _
                                         False, 100)
        Select Case iStatus
        Case WAIT_TIMEOUT
            ' Nothing happened
        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
        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
    Count = i
End Property

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


Author Comment

ID: 1429899
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.

LVL 14

Expert Comment

ID: 1429900
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


Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

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.

Join & Write a Comment

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

621 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