Use RegNotifyChangeKeyValue without WaitForSingleObject (Array)


I'm using the code suggested by Ark in this message, and it functions great. The problem occurs if I use this method wish a dynamic string array. Error details is given at the bottom.

Ark's method:


Dim strKeys() As String
Dim i as integer

For ListViewIndex = 1 To ListView1.ListItems.Count
 ReDim Preserve strKeys(i)
 RNumber = ListView1.ListItems(ListViewIndex).Text
 RPath = "Software\MyKey\" & RNumber
 strKeys(i) = RPath
 i = i + 1


====End of CODE=====

ERROR:  "ByRef Argument type mismatch" in variable "strKeys"

Perhaps I did something wrong in declaring the Array ? Any help would be appreciated.
LVL 34
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sRegKeyPath is declared as String, you are passing in an array.  That's why there is a Type Mismatch.
I believe you can monitor only one value at a time using this function, so you will have to pass in only one index: strKeys(0) for example.
If you need to monitor many different keys simultaneously you probably will need to move the code over to an ActiveX EXE and run a new instance for each key you need to montor.  Each "thread" will then be able to raise an event in your main program when a change occurs.
sramesh2kAuthor Commented:
Thanks for the insight, Erick. I noticed (and now removed) a duplicate "sub RegMonitor" and removed the duplicate one. Now, the error "Subscript out of range" error appears.

BTW, the error "ByRef Argument type mismatch" no longer appears now.

>> code over to an ActiveX EXE

Looks interesting, can you give me an example. I've never done an ActiveX Exe yet.
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

"Subscript out of range" means that the index you are using in an array is either too big or too small.
Make sure that i in strKeys(i) is within the bounds of the array.

If in doubt, use x = Lbound(strKeys) for the lower bound, and Ubound(strKeys) to test the upper bound.

Here is a pretty good example of using an ActiveX Exe worker thread:
Multi-Threaded VB Using ActiveX EXEs

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sramesh2kAuthor Commented:
Will try that, thanks. Let me reiterate the question again

From this PAQ:

It works perfectly if I use this format:
 Dim strKeys(2) As String
 strKeys(0) = "Software\VB and VBA Program Settings\Registry Notification\Hello"
 strKeys(1) = "Software\VB and VBA Program Settings\Registry Notification\Hello1"
 strKeys(2) = "Software\VB and VBA Program Settings\Registry Notification\Hello2"

In my case, the number of registry keys to monitor, varies (sometimes it's 10 keys, and sometimes it's 45 keys). How can I proceed with that? If that works, it's probably the simplest one that I know of.
Just change sRegKeyPath() As String to sRegKeyPath As Variant

PS Which VB version do you use? VB6 allow both ways (either sRegKeyPath() As String or sRegKeyPath As Variant) while VB5 allow Variant only
PS2: You also can add one more sub, smth like this:
'In a module:

Private Type KeyInfo
   RootKey As ROOT_KEY
   sName As String
   WatchSubTree As Boolean
   dwFilter As NOTIFY_EVENTS
End Type

Dim ki() As KeyInfo
Dim nKeys As Long
Public hEvent() As Long, bExit As Boolean

Public Sub AddKeyToMonitor (ByVal root As ROOT_KEY, ByVal sKey As String, ByVal lFilter As NOTIFY_EVENTS, ByVal bSubTree As Boolean)
   Redim Preserve ki(nKeys)
   ki(nKeys).RootKey = root
   ki(nKeys).sName = sKey
   ki(nKeys).WatchSubTree = bSubTree
   ki(nKeys).dwFilter = lFilter
   nKeys = nKeys + 1
End Sub

Public Sub StartRegMonitor()
   Dim lKeyHandle() As Long, lRet As Long, i As Long  

   If nKeys=0 Then Exit Sub
   ReDim hEvent(nKeys - 1)
   ReDim lKeyHandle(nKeys - 1)
   For i = 0 To nKeys - 1
       hEvent(i) = CreateEvent(0, True, False, vbNullString)
       lRet = RegOpenKey(ki(i).RootKey, ki(i).sName, lKeyHandle(i))
       RegNotifyChangeKeyValue lKeyHandle(i), ki(i).WatchSubTree, ki(i).dwFilter, hEvent(i), True
   Next i
     lRet = WaitForMultipleObjects(nKeys, hEvent(0), False, 100)
     If bExit Then Exit Do
     If lRet < nKeys Then
        MsgBox "Key " & ki(lRet).sName & " have been changed!"
        ResetEvent hEvent(lRet)
        RegNotifyChangeKeyValue lKeyHandle(lRet), ki(lRet).WatchSubTree, ki(lRet).Filter, hEvent(lRet), True
     End If
   For i = 0 To nKeys - 1
       lRet = RegCloseKey(lKeyHandle(i))
   Next i
End Sub
sramesh2kAuthor Commented:
Thanks, Ark for jumping in. Will implement as you suggest.
sramesh2kAuthor Commented:

>> Which VB version do you use?

I'm using VB6
sramesh2kAuthor Commented:

Actually, I'm enumerating a registry key, and populating the entries to a listview control. The listview control contains something like this (the number of keys varies):


They are the sub-keys of this registry key:

What I'm trying to do is to is to monitor each sub-key for changes simultaneously.

PS: I could monitor "HKCU\Software\MyKey" alone, but it does not notify which sub-key or value has changed. That's why I dropped that plan, and want to monitor each sub-key individually passing in an array.
sramesh2kAuthor Commented:
The error 9: "subscript out of range" occurs only if there are too many keys (more than 65 sub-keys), otherwise it functions great.

I've uploaded my test project here:

sramesh2kAuthor Commented:
Hi Eddykt,

Thanks. Is 64 the maximum that I can use?
according to mx, it is
sramesh2kAuthor Commented:
Excellent catch, Eddy. Based on your hint, got this article.

"Also, WaitForMultipleObjects does not allow you to pass an array of handles that exceeds 64 (MAXIMUM_ WAIT_OBJECTS) entries"

Now, I'll have to think about the workaround.
The workaround may be to monitor each key in an ActiveX exe object using WiatForSingleObject.  There will be no limitation on the number of instances of the class that you can create.  The worker object can then notify you in an event when a key has changed.
sramesh2kAuthor Commented:
I'm considering that option, Erick. Thanks again.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.

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.