0

As my title states, I am trying to move data from a C++ application I am writing and input it into a field (specifically username and password fields) on any desktop application in windows. It needs to work for all applications.

Now I have already written a small program which copies data to the clipboard, and then simulates a Ctrl+V keyboard press to paste the data in. This however, feels like a terribly ugly way to do this. My question is, is there a better way?

Ps. From the research I have done everything seems to require that you modify the receiving application in some way. This option is unfortunately unavailable to me. So any solutions involving tweaking the receiving application won't be helpful.

Thank you for your help!

  • There should be several examples that show you how to do this: http://stackoverflow.com/questions/2113950/how-to-send-keystrokes-to-a-window. If you need to set the focus of an input field I am sure there are ways to do this – Marged Apr 15 '16 at 08:52
  • Thank you! This definitely looks better, when I first came across this I was under the impression that this was not available for all applications. But it seems that I was mistaken. I'm going to try to implement that now. Also, I am new to stackoverflow, what is the proper thing for me to do now? Close the question? Upvote you somehow? – SledoMalset Apr 15 '16 at 09:22
  • @Marged: This requires, that the destination really is a native window (accessible through its `HWND`). This is often not the case, and the solution won't work. The documented and supported solution to automating UI's is [UI Automation](https://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx). – IInspectable Apr 15 '16 at 09:45
  • Ooops, until I posted my response, I did not see that the other question got an answer that uses SendMessage. I hope my response helps anyway. – Sam Hobbs Apr 16 '16 at 02:15
  • Your answer was very useful user34660! IInspectable: I guess this answers my comment farther down. If I understand you correctly there will be many applications which are not accessible through their HWND's? If this is the case, does UI Automation cover the remaining applications? In your experience, would you say that UI Automation would be ubiquitous enough to work generally across all applications? – SledoMalset Apr 21 '16 at 08:32

1 Answers1

0

Sending keystrokes to another application is not a good solution. There are many potential problems, such as in C# sendkeys to other application to particular textfield. A better solution is to interface with the other program more directly. It requires a bit more technical understanding of how Windows works however. One of many advantages is that you can read text in the other application as easily as write it.

See my Clicking a Button in Another Application for a sample, but that is in C#. I hope the explanation at least is helpful. The same technique can be used to put data into a text box or text boxes then click a button. The WM_SETTEXT message would be used to put data into a textbox in another application. The following is a sample console program that puts text into Notepad.

#include "stdafx.h"

struct pidandhwnd {
    DWORD dwProcessId;
    HWND hwnd;
};

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    pidandhwnd *ppnh = (pidandhwnd *)lParam;
    DWORD dwProcessId;
    GetWindowThreadProcessId(hwnd, &dwProcessId);
    if (ppnh->dwProcessId == dwProcessId)
    {
        ppnh->hwnd = hwnd;
        return FALSE;
    }
    return TRUE;
}

int main()
{
    TCHAR szCmdline[] = TEXT("Notepad.exe");
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    BOOL bSuccess = FALSE;

    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
    siStartInfo.cb = sizeof(STARTUPINFO);
    siStartInfo.hStdError = NULL;
    siStartInfo.hStdOutput = NULL;
    siStartInfo.hStdInput = NULL;

    LPARAM lParam = NULL;
    pidandhwnd pnh;

    const int ControlId = 15;   // Edit control in Notepad
    HWND hEditWnd;

    bSuccess = CreateProcess(NULL,
        szCmdline,     // command line 
        NULL,          // process security attributes 
        NULL,          // primary thread security attributes 
        TRUE,          // handles are inherited 
        0,             // creation flags 
        NULL,          // use parent's environment 
        NULL,          // use parent's current directory 
        &siStartInfo,  // STARTUPINFO pointer 
        &piProcInfo);  // receives PROCESS_INFORMATION 
    if (!bSuccess) {
        std::cout << "Process not started\n";
        return 0;
        }
    std::cout << piProcInfo.dwProcessId << " Notepad Process Id\n";

    WaitForInputIdle(piProcInfo.hProcess, 1000);

    pnh.dwProcessId = piProcInfo.dwProcessId;
    pnh.hwnd = NULL;
    EnumDesktopWindows(NULL, EnumWindowsProc, (LPARAM)&pnh);
    if (pnh.hwnd == NULL)
    {
        std::cout << "Notepad not found\n";
        return 0;
    }
    //std::cout << "Notepad found\n";

    // Get the edit box on Notepad
    hEditWnd = GetDlgItem(pnh.hwnd, ControlId);
    // Send the text
    SendMessage(hEditWnd, WM_SETTEXT, NULL, (LPARAM)_T("This is from somewhere else."));

    return 0;
}
Community
  • 1
  • 1
Sam Hobbs
  • 2,594
  • 3
  • 21
  • 32
  • Thank you for the detailed answer!( and sorry for my slow response to it) I have a few follow up questions if that's alright. The clicking a button example seems like it could be very useful to me, however I am still not 100% in my OS knowledge. Are there applications that are impervious to spy++? That is to say, is there a specific class of applications in which I will not be able to access the text boxes (in my case username/password), or is the OS such that these fields will always be accesible to spy++? – SledoMalset Apr 21 '16 at 08:27
  • I apologize for not seeing this sooner. This won't work with software using newer technology but I don't know if there is an equivalent solution. I also don't know how well applications can protect themselves from this kind of thing. They can some but probably not totally. You can create a new question to ask about specifics. – Sam Hobbs Apr 26 '16 at 01:11