I have an issue trying to get a keyboard hook for the current thread.
Firstly, I needed to get keyboard input for all threads, so I used :
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, mKeyboardProc, GetModuleHandle(NULL), 0);
This works fine, but when I try to set the dwThreadId parameter (the last one) to GetCurrentThreadId(), SetWindowsHookEx returns NULL.
What could be the problem ?
Thanks.
WH_KEYBOARD_LL is a global hook, as stated in the documentation. That means that you must pass 0 for the thread ID parameter.
You could have diagnosed this yourself had you called GetLastError, as described by the documentation. This would have returned error code ERROR_GLOBAL_ONLY_HOOK, This hook procedure can only be set globally.
Related
is it possible to determine if a SendMessage() call was successful and delivered my message to the target window?
The SendMessage() description in the Windows API seems quiet on this and only says the following:
The return value specifies the result of the message processing; it depends on the message sent.
This obviously refers to the fact that the return code reflects the value returned by the wndproc of the target window.
But what will the return code be if the message wasn't delivered at all (e.g. due to access control, or due to the window having been destoroyed in the meantime)? How can I detect such situations?
There is no way to reliably tell, whether a call to SendMessage succeeded or failed. After all, it only has a single return value, and the entire range of values is used. There is no designated error value.
Playing tricks with the calling thread's last error code won't work either. The scheme proposed in this answer (clearing the last error code prior to the call and evaluating it after the call) is brittle. It's easy to see that it can fail, when sending a message to a window owned by the calling thread (as that window's window procedure is at liberty to change the last error any way it sees fit).
It's not quite as well known, that this can also fail when sending a message to a window owned by a different thread. The code suggests, that no intervening API call can happen in the calling thread. Yet in that scenario, SendMessage will also dispatch incoming cross-thread messages (see When can a thread receive window messages?), allowing the thread's last error code to change.
The only option then is to use SendMessageTimeoutW, as that API reports both the result of the call, as well as an error/success indicator. Passing the SMTO_NOTIMEOUTIFNOTHUNG flag makes sure that an arbitrarily chosen timeout will not adversely affect the outcome.
if SendMessage fail, it set last win32 error code, which we can get back via call GetLastError(). and returned error code, in case fail, never will be 0 (NOERROR) despite this is clear not documented. but how detect that SendMessage is fail ? here we can not base on return value. but we can SetLastError(NOERROR) before call SendMessage and check GetLastError() after:
if SendMessage fail - value returned by GetLastError() will be
not 0. (most common in this case ERROR_INVALID_WINDOW_HANDLE or
ERROR_ACCESS_DENIED).
if we still got 0 as last error - this mean that message was
delivered with no error.
however, possible case, when during SendMessage call, some window procedure
in current thread will be called and
code inside window procedure, set last error to non 0 value. so we
get finally not 0 last error, but not because SendMessage fail.
distinguish between these two cases very problematic
-
SetLastError(NOERROR);
LRESULT lr = SendMessageW(hwnd, *, *, *);
ULONG dwErrorCode = GetLastError();
if (dwErrorCode == NOERROR)
{
DbgPrint("message was delivered (%p)\n", lr);
}
else
{
DbgPrint("fail with %u error\n", dwErrorCode);
}
I've written a simple launcher that looks up the actual program and then executes it. This works fine, but there is one issue: Windows displays the "pointer with hourglass" cursor for about give seconds. This does not happen if I launch the program directly.
I tried setting sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK but this did not help. I guess that's because it's my program that somehow needs to disable the cursor and the program I start does that fine (it creates a proper window etc.).
This is the relevant code from my application. I do not have any threads or any other fancy stuff (the sole purpose of the program is to launch another program and pass on the exit code to its caller in case it cares about it):
STARTUPINFO sinfo = {0};
PROCESS_INFORMATION pinfo = {0};
if (!CreateProcess(program, buf, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo)) {
Fail("Could not launch Vim");
}
if (WaitForSingleObject(pinfo.hProcess, INFINITE) == WAIT_FAILED) {
Fail("WaitForSingleObject");
}
Apparently Windows expects a Windows program to process messages and does not consider it fully started before that point, which is why it shows the appstarting cursor.
Adding the following code to process a single dummy message solved the problem:
MSG msg;
PostMessage(NULL, WM_NULL, 0, 0);
GetMessage(&msg, NULL, 0, 0);
Your program is showing the hour-glass icon because your UI thread is hanging as a result of being stalled on the WaitForSingleObject call. Remember, WaitForSingleObject does not return until after the child process exits. You could substitute the Wait call with a Sleep and get the same effect.
You have some options:
Use MsgWaitForMultipleObjects instead of WaitForSingleObject. This is the more formal way to pump messages and wait at the same time instead of the PostMessage/GetMessage thing you suggest in your own answer.
Do the Wait call on another thread. When the thread returns, it PostMessage something to your UI thread to indicate it is done.
In both of the above cases, the UI will become responsive to clicks and input events while the child process is still happening. You will need to code your UI thread to handle this as appropriate (if it's warranted).
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?
My application needs to monitor all other running applications on the system. Is there some way I could get notified on exit of every application exe?
The methods I could find:
1) Use PSAPI functions to get the list of running exes at frequent intervals. At each poll compare with the previous list to find which application/process has exited.
Disadvantage: Requires constant polling, will take CPU time.
2) Set a global hook for WM_CLOSE message: Using this I would be able to get a notification when any application gets closed through the close button on the title bar
Disadvantage:
(-)Not all the applications are generating a WM_CLOSE message(Ex: Total Video Player Exe)
(-)If the application was closed through the "Exit" menu or button (e.g. File->Exit) , I can't trap that message
Is there any other better way that I missed? Please advise.
Get a list of PIDs using PSAPI.
Then get a handle on each process using OpenProcess().
Use WaitForMultipleObjects() to be signalled when one of the processes exits.
You could try the RegisterShellHookWindow() API and filter for HSHELL_WINDOWCREATED and HSHELL_WINDOWDESTROYED messages.
Of course, that will only get you notified about applications that have a window.
I recently ran into this problem and found a solution so wanted to share with you all. It all correct the way we should obtain handle to the process. Instead of WaitForSingleOBject though, I would recommend to use RegisterWaitForSingle object function. With this function you are giving a callback function and whenever the process exits, your callback function will be called. This is better than calling WaitForSingleObject in a thread. Calling WaitForSingleObject in your code by itself will cause your code to wait until the process exits. Here is an example of how to call it:
RegisterWaitForSingleObject(&waitHandle, processHandle, ProcessTerminatedCallback, param, INFINITE, WT_EXECUTEONLYONCE);
Where:
[out]waitHandle - new handle created for you. Please note that you cannot use this handle to call CloseHandle, but you can wait on it, if you want to.
[in] processHandle - handle to the process that you are supposed to obtain yourself
[in] ProcessTerminatedCallback - the callback function that will be called when the process exits
[in] param - LPVOID parameter that will be passed to the callback
[in] INFINITE - either wait infinitely or for a specified time, look up MSDN for more info
[in] WM_EXECUTEONLYONCE - will call the callback function only once. look up MSDN for more info
> Is there any other better way that I missed?
Yes, plenty. See on Win32 group (system notifications, without any hook)
I am getting confused with the SetTimer() function.
SetTimer() takes three parameters:
SetTimer(1,2000,Timerflow);
However I've seen another version of SetTimer that takes four parameters:
SetTimer(NULL,1,2000,Timerflow);
What is the difference between these two functions?
I know SetTimer() Three parameters. But when I try the four parameter SetTimer() function, I get the error:
error C2660: 'SetTimer' : function does not take 4 parameters
So what is the main difference and what causes this error?
The 4-parameter version is the plain Win32 API version, and the first parameter is a window handle.
The 3-parameter version is a member of MFC's CWnd class, and works with the window handle of the CWnd instance for which you call it.
If you need to call the 4-parameter Win32 API from within a method of a CWnd-derived object, do this:
::SetTimer(NULL, 1, 2000, Timerflow);
The only Windows API called SetTimer takes four parameters. Presumably the other one is part of MFC or some other framework, and the first parameter is implied by the object you call it on. For example:
CWnd * w = .... // get window somehow
w->SetTimer(1,2000,Timerflow);
If you use SetTimer to create a timer in GUI classes such as the MFC's CWnd, you can use the 3-parameter form:
UINT SetTimer(
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
But if you use it in non-GUI classes, you have to use the 4-parameter form. The first parameter is to specify which GUI component will respond for the timer event. This version of the function is called from Win32 API.
eUINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
It is very simple, isn't it?
According to MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx, the first and last parameters are optional. Therefore, you can have a SetTimer call with even 2 parameters (not recommended however). The error is most likely from an incorrect cast (needs a uint_ptr, you give an hwnd, for example)