Discussion:
How to make SendInput or PostMessage work?
(too old to reply)
Norman Diamond
2006-01-27 05:51:32 UTC
Permalink
SendInput, PostMessage, etc., are supposed to be capable of sending user
input to a window. If it's the foreground window and the caller has a
handle and sufficient privileges, the functions indicate success. But
depending on what application owns the window, maybe the input gets there or
maybe the input is discarded. What is needed to make either SendInput or
PostMessage work reliably? (Preferably SendInput if it can be done
reliably.)

Working: cmd.exe, gvim.exe
Input discarded: notepad.exe, winword.exe, wordpad.exe
Norman Diamond
2006-01-27 06:33:06 UTC
Permalink
Post by Norman Diamond
Working: cmd.exe, gvim.exe
Input discarded: notepad.exe, winword.exe, wordpad.exe
Oops, the above is only for PostMessage.

Trying to use SendInput, behaviour is worse.
Input discarded: cmd.exe, gvim.exe, notepad.exe, winword.exe, wordpad.exe
Norman Diamond
2006-01-27 07:23:22 UTC
Permalink
Post by Norman Diamond
Post by Norman Diamond
Working: cmd.exe, gvim.exe
Input discarded: notepad.exe, winword.exe, wordpad.exe
Oops, the above is only for PostMessage.
Now I have SendInput working, and probably no longer need help. For
intellectual curiosity though, the aforementioned behaviour of PostMessage
still looks very strange. Here's the code:

if (!PostMessage(g_ConsoleForegroundWindowHandle,
WM_KEYDOWN, 'W', ((0x00 << 24) | (0x11 << 16) | 1))) {
DWORD Error = GetLastError();
Out(_T("PostMessage"));
return Error;
}
if (!PostMessage(g_ConsoleForegroundWindowHandle,
WM_KEYUP, 'W', ((0xC0 << 24) | (0x11 << 16) | 1))) {
DWORD Error = GetLastError();
Out(_T("PostMessage"));
return Error;
}

Temporarily I added an additional call to OutputDebugString to display the
window handles, and used VC++6's Spy++ to check the handles, and they were
accurate. If the handle was for a window running gvim.exe or cmd.exe, no
problem, it got a 'w' every second. (The keyboard state was unshifted so
the 'W' key yielded lower-case 'w'.) If the handle was for a window running
notepad.exe, winword.exe, or wordpad.exe, the key didn't get there. If
anyone happens to know how this can happen, I'm still interested.
Jeffrey Tan[MSFT]
2006-01-27 08:07:24 UTC
Permalink
Hi Norman,

Thanks for your post.

Based on my understanding, you want to send a WM_KEYDOWN message to other
application to simulate keyboard input.

I can confirm that PostMessage should work for Notepad, because I used it
in a simple application some time before. However, regarding your scenario,
I do not recommand you to use SendMessage/PostMessage API. They are not
suitable for sending keyboard input.

Normally, we can use keybd_event API to simulate the keyboard input. This
API is reliable for generate keyboard event for current focused window.
System will detect this new generated keyboard event and generate WM_KEYUP
or WM_KEYDOWN message for us. For more information, please refer to MSDN
reference.

Hope this helps

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Norman Diamond
2006-01-27 08:37:09 UTC
Permalink
Post by Jeffrey Tan[MSFT]
Based on my understanding, you want to send a WM_KEYDOWN message to other
application to simulate keyboard input.
First a message with WM_KEYDOWN, followed by a message with WM_KEYUP.
Post by Jeffrey Tan[MSFT]
I can confirm that PostMessage should work for Notepad, because I used it
in a simple application some time before.
But I still confirm that it doesn't work. Very oddly it works with gvim.exe
and cmd.exe but not with notepad.exe, winword.exe, or wordpad.exe.
Post by Jeffrey Tan[MSFT]
However, regarding your scenario, I do not recommand you to use
SendMessage/PostMessage API.
Agreed. I tried them during the time that I was having trouble with
SendInput. Now I have SendInput working, and only for intellectual
curiosity I still wonder why PostMessage is unreliable.
Post by Jeffrey Tan[MSFT]
Normally, we can use keybd_event API to simulate the keyboard input.
Yes, though MSDN says to use SendInput instead of keybd_event, unless we
have to support Windows 98/ME.
Post by Jeffrey Tan[MSFT]
This API is reliable for generate keyboard event for current focused
window.
If I neglected to open WinSta0, get the input desktop, and set the thread
desktop, then SendInput failed. I didn't try it with keybd_event.

Actually I still think that WinSta0 isn't always the correct window station
to open. I want to open whichever window station is in use on the actual
console. If fast user switching has been used then the window station might
not be WinSta0. If no one is logged into the actual console then I'm not
sure yet, either the welcome screen or maybe not open any window station.
(In this app I never want to open a window station of anyone who is logged
in through an terminal service session, not by accident and not for any
reason.)
Jeffrey Tan[MSFT]
2006-01-27 09:11:04 UTC
Permalink
Hi Norman,

Thanks for your feedback.

Oh, you are correct. Every window station has its own logical combination
of a keyboard, a mouse, and a display. So we can not use
SendInput/keybd_event or SendMessage/PostMessage to send input cross window
station.

To do this, we can use some hook technology(such as CreateRemoteThread for
LoadLibrary, etc..) to inject some code into a process which resides in the
real console window station. Now, this code executes in Winsta0, and we can
use SendInput to generate the keyboard event. Keith Brown's Session Viewer
tool uses this technology. You can download the session viewer tool and
source code in the link below:
http://www.develop.com/technology/resourcedetail.aspx?id=154fb42b-504f-4959-
9e18-332848ebfb74

Also, if your service runs under Local System account, you can just open
the Winsta0 and interactive desktop, then swtich to the interactive
desktop. With this, we can use SendInput to generate the keyboard event
now.

Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
anton bassov
2006-02-19 02:33:47 UTC
Permalink
Hi mate


In order to simulate input, you should call SendInput() - calling
PostMessage is NOT(!!!) the right way of simulating keyboard or mouse events.
However, you must make sure that the window that you want to receive the
message currently holds keyboard focus. You have to do it with SetFocus().
If the target window has been created by the thread, different from the one
that calls SetFocus(), you have to attach input of the calling thread to the
target one( you can do it with AttachThreadInput())before calling SetFocus()




Anton

Loading...