0

Background:

I'm sending keystrokes to a program (Text Editor) that I hide and then Send the F7 Key and after that four keys of text (kind of a password). I'm using JNA Library and the SendMessage function of Win32API to send the messages, can't use sendInput() because I need to send to a specific window handle.

Code:

private static void sendInputToWindow(WinDef.HWND editorWindowHandle, char[] password) throws InterruptedException {
        User32.INSTANCE.ShowWindow(editorWindowHandle, WinUser.SW_HIDE);
        User32.INSTANCE.SetForegroundWindow(editorWindowHandle);
        User32.INSTANCE.SetFocus(editorWindowHandle);

        //F7 KEY SENT
        WinDef.WPARAM wparam = new WinDef.WPARAM(F7_VIRTUAL_KEY);
        WinDef.LPARAM lparam = new WinDef.LPARAM(0);
        log.debug("SENDING F7");
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_KEYDOWN, wparam, lparam);
        Thread.sleep(1000);
        log.debug("SENDING PASSWORD");
        // PASSWORD SENT
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_CHAR, new WinDef.WPARAM(password[0]), lparam);
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_CHAR, new WinDef.WPARAM(password[1]), lparam);
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_CHAR, new WinDef.WPARAM(password[2]), lparam);
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_CHAR, new WinDef.WPARAM(password[3]), lparam);
        Thread.sleep(500);
        log.debug("SENDING ENTER");
        // ENTER KEY SENT
        User32.INSTANCE.SendMessage(editorWindowHandle, WinUser.WM_KEYDOWN, new WinDef.WPARAM(ENTER_KEY), lparam);
    }

Problem:

When I am sending Keystrokes through SendMessage, after some time or randomly ( I don't know what's causing the issue here ) but sometimes it does not send the keystrokes at all!

So it's a hit or miss situation, most of the times it sends the keystrokes while other times it does not. I wonder if there is a better way to send keystrokes to a hidden window? or if I am doing something wrong here.

Thank You.

Bakar
  • 383
  • 1
  • 9
  • 27
  • 2
    There is no single mechanism to do this. `SendInput` is the supported way to fake input. Anything else is just hacking. Certainly you cannot expect to directly send `WM_CHAR` messages. Exactly what will work for you depends on the target (aka victim) window. As is so often the case in the multitude of input faking questions we see here, that vital detail has been omitted. For instance, if this is just a Win32 edit control, you can use `WM_SETTEXT`. But we don't actually know what this control really is. – David Heffernan Jun 11 '19 at 11:48
  • There's [UI Automation](https://learn.microsoft.com/en-us/windows/desktop/winauto/entry-uiauto-win32) if indeed you want to automate a UI. – IInspectable Jun 11 '19 at 12:25
  • @IInspectable is it usable through a Java Library (as in JNA) or do I have to use JNI for that ? – Bakar Jun 11 '19 at 13:48
  • @DavidHeffernan Thank you for the insight on that. I'm using `SendInput` now along with a combination of `SetFocus` as in (SetFocus --> SendInput). It seems to working for now. No need fro `WM_SETTEXT` as it is not an edit control. – Bakar Jun 11 '19 at 13:50
  • The mystery continues. Knowing what this control is **not** makes it hard for anybody to help you. Why not let us all know what it **is**. – David Heffernan Jun 11 '19 at 14:04
  • I don't know the naming of windows components since I have only novice knowledge of the Win32API. I open a custom editor with a text file(which is to be E-Signed) and then hide it (so it basically doesn't get shown to end user ). Then Press `F7` key to start E-Signing process. The User gives the password when launching the jar ( password is 4 digit for smartcard). After that it signs the file and closes the editor. That's all it does. I'm still testing with SendInput, if it passes all envs and cases and Ill update the answer. I hope that made it clearer. – Bakar Jun 11 '19 at 14:42
  • 1
    UI Automation is exposed as a set of COM objects. COM is language agnostic. I would be surprised to find out, that there were no JNA wrapper for COM, or even a pre-built UI Automation library (like [this](https://github.com/mmarquee/ui-automation) one). – IInspectable Jun 11 '19 at 15:24
  • Asked here, with the same answer of "probably can't be done": https://stackoverflow.com/questions/54313354/simulate-keystrokes-in-inactive-windows – Daniel Widdis Jun 11 '19 at 22:43
  • hi, AbuBakar I tried to reproduce your problem on the Win32 console, but I didn't use SendMessage to send keystrokes without sending them.Here is my codes. – Strive Sun Jun 13 '19 at 07:29
  • 1
    LPCWSTR Target_window_Name = TEXT("print.txt - Notepad"); HWND hWindowHandle = FindWindow(NULL, Target_window_Name); LRESULT result = SendMessage(hWindowHandle, WM_SETFOCUS, 0, 0); std::cout << GetLastError() << std::endl; while (1) { SendMessage(hWindowHandle, WM_KEYDOWN, 0x118, 0); //"F7" Sleep(1000); SendMessage(hWindowHandle, WM_CHAR, 0x31, 0); //"1" SendMessage(hWindowHandle, WM_CHAR, 0x32, 0); //"2" SendMessage(hWindowHandle, WM_CHAR, 0x33, 0); //"3" SendMessage(hWindowHandle, WM_CHAR, 0x34, 0); //"4" Sleep(500); SendMessage(hWindowHandle, WM_CHAR, 0x0D, 0); //"Enter" } – Strive Sun Jun 13 '19 at 07:30
  • my environment : window 10 , vs2017 ; Please tell me if there is anything missing. – Strive Sun Jun 13 '19 at 07:30
  • @StriveSun-MSFT I open the process send keystrokes ( as you did ) and then close it, then open again. It works for a few files but then doesn't send keystrokes. Also SendMessage gives a '0' as a result even if it works successfully. – Bakar Jun 13 '19 at 08:05
  • When you reopen the process, do you notice if you have successfully obtained the handle of the text editor correctly? – Strive Sun Jun 13 '19 at 08:19
  • @StriveSun-MSFT Yes, I checked that as well. Is SendMessage Robust as compared to SendInput? If it is then I think the problem might be with the program itself. – Bakar Jun 13 '19 at 09:22
  • These two APIs are based on requirements.The `SendMessage` function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.The `SendInput` function synthesizes keystrokes, mouse motions, and button clicks. – Strive Sun Jun 13 '19 at 10:29

1 Answers1

2

As stated in the commentary, SendInput is the most supported.

I tried to use it in the Win32 console and found that it worked very well. The code is as follows.

#include <iostream>
#include <Windows.h>

int main()
{
    INPUT input[5];
    memset(input, 0, sizeof(input));

    input[0].type = input[1].type = input[2].type = input[3].type = input[4].type = INPUT_KEYBOARD; 
    SetForegroundWindow((HWND)0x000A09D8);//EDIT EDITOR HANDLE

    while (1)
    {       
        input[0].ki.wVk = '1';
        input[1].ki.wVk = '2';
        input[2].ki.wVk = '3';
        input[3].ki.wVk = '4';
        input[4].ki.wVk = VK_RETURN;

        SendInput(5, input, sizeof(INPUT));
        std::cout << GetLastError() << std::endl;
        Sleep(1000);
        input[0].ki.dwFlags = input[1].ki.dwFlags = input[2].ki.dwFlags = input[3].ki.dwFlags = input[4].ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(5, input, sizeof(INPUT));
        input[0].ki.dwFlags = input[1].ki.dwFlags = input[2].ki.dwFlags = input[3].ki.dwFlags = input[4].ki.dwFlags = 0;
        std::cout << GetLastError() << std::endl;
        Sleep(1000);
    }

    return 0;
}

print

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • 1
    but this requires the window handle to focused, so if I set it as Foreground and set Focus to the window only then I can send it. Is there any way to send to a background window or force focus ? – Bakar Jun 13 '19 at 11:03
  • @AbuBakarKhan `SendInput` has no handle parameter, so it cannot be sent to the background window – Strive Sun Jun 13 '19 at 11:13
  • @AbuBakarKhan `SendMessage` can be sent to the background window, but it can not guarantee the accurate transmission of the message.That's what you're worried about.I read some information, which @IInspectable mentioned , use `UI Automation`. It's the only supported way to automate a UI without bringing it into the foreground. – Strive Sun Jun 13 '19 at 11:29