I have some code that collects all the window handles into an array. The problem is, since the callbacks are done asynchronously, i dont know when the enumeration is actually finished. What is the best approach to solving this? I assume this is a common problem in windows programming.
BOOL CALLBACK enumWindowsProc3(HWND hwnd, // handle to parent window
LPARAM lParam // application-defined value
) {
//add hwnd to array
return TRUE;
}
int howManyWindows() {
EnumWindows (enumWindowsProc3, 0);
// need to wait here for EnumWindows() to finish...
return array size
}
I'm not a Windows API expert, but this is a general programming problem.
If you have access to a semaphore type structure that can wait(),signal(),and give you a count of items, then you can block the thread until a certain count is reached. Each asynchronous query to the window would then signal() to the semaphore.
Otherwise you can do a general poll checking the completion of all items but make sure that the thread goes to sleep for a certain amount of time while in the poll loop.
EnumWindows callbacks are synchronous, not async. No wait is required. Code after EnumWindows will execute only after all callbacks have been completed...
Related
I am using ReadDirectoryChangesW to monitor when a file has changed within a directory. I am using the asynchronous version of it with a completion routine function, (as per the docs).
Everything works fine until I wish to stop monitoring the folder.
To stop the monitoring I call the Close function.
The problem is that I still get one last notification, but by then I have destroyed my LPOVERLAPPED value.
How can I stop ReadDirectoryChangesW and prevent my MyCompletionRoutine function from being called.
// get the handle
_handle = CreateFileW( ... )
void Read()
{
...
ReadDirectoryChangesW( _handle, ..., &MyCompletionRoutine );
...
}
void Close()
{
::CancelIo(_handle );
::CloseHandle(_handle );
}
void __stdcall MyCompletionRoutine (
const unsigned long dwErrorCode,
const unsigned long dwNumberOfBytesTransfered,
_OVERLAPPED* lpOverlapped )
{
// ... do stuff and start a read again
Read();
}
In the code above I might have called Read but I want to stop before MyCompletionRoutine is called.
Not sure if that helps, but the error message I get is 317
You are closing your HANDLE and freeing your OVERLAPPED too soon.
CancelIo() (and its cross-thread brother, CancelIoEx()) simply mark active I/O operations as cancelled and then exit, but you still need to actually wait for those operations to fully complete before you can then free their OVERLAPPED.
If an operation notices the cancellation before completing its work, it will stop its work and report a completion with an error code of ERROR_OPERATION_ABORTED, otherwise it will finish its work normally and report a completion with the appropriate error code.
After calling CancelIo/Ex(), you need to continue waiting on and handling completed operations, until there are no more operations left to wait on.
In other words, MyCompletionRoutine() can indeed be called after CancelIo() is called, and it needs to check for ERROR_OPERATION_ABORTED before calling Read() again. And if there is a pending read in progress when CancelIo() is called, you need to wait for that read to complete.
I'm trying to figure out how to use FindFirstChangeNotification in order to do some file monitoring (in this case, for hot-reloading settings). I'm a bit a confused about what this function returns. From the docs, it creates a "change notification handle". Ok, sure. But then "A wait on a notification handle succeeds when...". In this context, what is a "wait"?
In this context, the "wait" refers to wait for the "change notification handle", which is a kind of HANDLE that you can wait until it is in signaled state by using Wait Functions.
A minimal example would be like this:
static void MyNotifyDirChange(HWND hwnd, LPCWSTR szPath)
{
HANDLE hWaitNotify = ::FindFirstChangeNotificationW(
szPath, TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_LAST_ACCESS |
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SECURITY);
if (hWaitNotify == INVALID_HANDLE_VALUE)
{
::MessageBoxW(hwnd,
L"FindFirstChangeNotificationW failed.",
nullptr, MB_ICONERROR);
return;
}
::WaitForSingleObject(hWaitNotify, INFINITE);
::MessageBoxW(hwnd, L"Dir change notify.",
L"Notify", MB_ICONINFORMATION);
}
WaitForSingleObject waits until the specified object is in the signaled state or the time-out interval elapses. Since I've specified INFINITE, it will stay at there forever until the handle became signaled. And when the handle became signaled, it means something has happened; the files in the directory have changed or whatnot.
From Wait Functions on MSDN:
Wait functions allow a thread to block its own execution. The wait functions do not return until the specified criteria have been met.
Most of the wait functions (the notable exception being WaitOnAddress) accept one or more handles that determine the criteria for returning from the wait. To wait on a handle means to pass the handle to one of these wait functions. It is also common to refer to waiting on an object, which has the same meaning as waiting on a handle to that object.
Synchronization Objects lists the various kinds of objects you can wait on: events, mutexes, semaphore and waitable timers; change and memory resource notifications; jobs, processes and threads; and (subject to some caveats) I/O handles.
My app spawns a thread, in this thread i do the following code:
function myLLMouseHook_js(nCode, wParam, lParam) {
var rez_CallNext = CallNextHookEx(null, nCode, wParam, lParam);
console.info('rez_CallNext:', rez_CallNext, rez_CallNext.toString());
return rez_CallNext;
};
aHhk = SetWindowsHookEx(WH_MOUSE_LL, myLLMouseHook_c, null, 0);
It registers properly, however for 5 seconds it freezes my mouse, it doesnt move or nothing (keyboard input works at this time). Callback is never fired. If I attempt unhook on aHhk it returns true. It's so odd. The thread is alive and running.
If I run this same code from main thread it works flawlessly. Does anyone hvae any ideas?
Forgive the many issues on this lately, im working on solving one goal of monitoring mouse via multiple (sync/blocking, async/copy of events so non-blockable[the raw input api method was giving probs due to no access to WndProc]) methods to write in tutorials.
Likely explanation is that the thread is not running a message loop. As documented, low level hooks need the hook's owning thread to run a message loop.
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
I'm trying to use event object in win32 environment to synchronize two processes. Below are the simplified code of two programs.
// process1
int main()
{
HANDLE h = CreateEvent(NULL, FALSE, FALSE, TEXT("Hello"));
WaitForSingleObject(h, INFINITE);
// RunProcess(L"process2.exe", L"");
}
// process2
int main()
{
HANDLE h = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("Hello"));
SetEvent(h);
}
It's quite simple, and works well when two processes are launched independently. However it does not work when the process 1 launches process 2 as a child process (which is commented in the above code) - the SetEvent call fails. What is the reason and solution of this problem?
Your code needs to check and handle errors. Both CreateEvent and OpenEvent will return NULL if they fail, in that case you need to check the error using GetLastError.
Your calls to WaitForSingleObject and SetEvent should be checked per the MSDN docs as well.
The order in which you need to do things in the parent process is:
CreateEvent
Start child process
WaitForSingleObject.
Otherwise you will hit the problem called out by #Mark Tolonen.
It would also be best to have a timeout on your wait, to handle the case where the child process fails to start, exits unexpectedly, or hangs.
An alternative approach if you intend to use this parent/child relationship would be to allow inheritance of the event handle. Then the event does not need to be named, and nobody else can 'squat' on it in a DoS attack on your apps. You can pass the handle value to the child as a command-line parameter. You do this using the bInheritHandle field on the eventAttributes parameter to CreateEvent.
A Boolean value that specifies whether
the returned handle is inherited when
a new process is created. If this
member is TRUE, the new process
inherits the handle.
Are you sure? As written, if process1 creates process2 in the current location, it will never create process2 because it will wait forever for the event to be fired. Create process2 first, then wait for the event to be set.
You have a NULL security descriptor, which the documentation says cannot allow the handle to be inherited by children processes, specifically:
If this parameter is NULL, the handle cannot be inherited by child processes
Maybe you need to create a proper security descriptor?
I'm calling a subroutine form the WndProc function in a windows app. WndProc was called from the message processing loop when a button was pushed. The subroutine takes a fair amount of time to run so it sends periodic messages using SendMessage(WM_USER). These messages should cause screen updates. Unfortunately, the updates are all held until the subroutine returns; at that time all the messages are processed and the screen updated. The handler for the message is in WndProc; it invalidates the window which should cause a paint message to be generated.
Do I need to run the subroutine as a separate thread?
If you want your UI to remain responsive while the subroutine runs, you either have to pump messages within the subroutine (which can itself get you into re-entrancy nasties), or move the subroutine out to a thread. The preferred way to do this is with a Worker thread.
There's an intro to worker threads on my website here. When the thread finishes its work, you can post a registered message back to your main window. Worker threads are pretty easy.
Anticipating your next question about cancelling a lengthy operation, there's a discussion of the options available to you for doing that on my site here. Warning, some of them are very silly, but I do try to be complete :-)
The best would be to use a separate thread.
But you could run the message loop in your handler function too:
HWND hwnd;
BOOL fDone;
MSG msg;
// Begin the operation and continue until it is complete
// or until the user clicks the mouse or presses a key.
fDone = FALSE;
while (!fDone)
{
fDone = DoLengthyOperation(); // application-defined function
// Remove any messages that may be in the queue. If the
// queue contains any mouse or keyboard
// messages, end the operation.
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_KEYDOWN:
//
// Perform any required cleanup.
//
fDone = TRUE;
}
}
}