Click here to Skip to main content
15,885,032 members
Articles / Desktop Programming / MFC
Article

A class for the automation of simple computer tasks using keybd_event and CreateProcess

Rate me:
Please Sign up or sign in to vote.
4.44/5 (9 votes)
17 Mar 20067 min read 54.7K   966   27   9
This class uses keybd_event and CreateProcess to create a script processor and executor. The script can be used for automation of daily tasks such as opening and checking mail accounts, automating the functionality of software etc. This will work with any app which can take input via keyboard.

Sample Image - Sendkeys.jpg

Introduction

The Windows keybd_event mechanism is useful in many ways, specially in automation of tasks such as entering input etc. But its capability is restricted by the fact that it can be a little tedious for entering large number of key combinations which can be variable and which cannot be programmed easily. So I have done all the dirty work for you. You have to just include the class I provide in your program, and then you can form a script and use the class methods to run the script. This script can be used to automate any task that can be accomplished using the keyboard. This can be a real blessing if you are as lazy as I am. Also, the CreateProcess method is used for creating new processes like Winamp, IE etc.

Elementary keybd_event and CreateProcess

According to MSDN the keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function. For example, if you want to simulate the pressing of the Enter key, then you have to use the keybd_event once for pressing down the key and then again for releasing the key, like in the example given below:

keybd_event(VK_RETURN, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);

In order to simulate the pressing of a key combination like ALT+ENTER, you have to first press down ALT, then press ENTER, then release ENTER, and then release ALT, like below:

keybd_event(VK_MENU, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
::Sleep(50);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);

VK_MENU and VK_RETURN are the codes for the ALT and ENTER keys. Instead of the virtual key code, you can also pass the corresponding hex values. An official table containing the keys and their codes is given here.

CreateProcess can be used to create a new application or process by passing its executable file as a parameter. Its usage is been given below, and the example opens a new Notepad window.

TCHAR szCmdline[]=TEXT("notepad");

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi) );

// Start the child process. 
CreateProcess( NULL,   // No module name (use command line)
    szCmdline,      // Command line
    NULL,           // Process handle not inheritable
    NULL,           // Thread handle not inheritable
    FALSE,          // Set handle inheritance to FALSE
    0,              // No creation flags
    NULL,           // Use parent's environment block
    NULL,           // Use parent's starting directory 
    &si,            // Pointer to STARTUPINFO structure
    &pi ) ;          // Pointer to PROCESS_INFORMATION structure

After creating the process, if you want to pass any keyboard input to it, then you will have to first set focus on the newly created process. This can be done by using the SetFocus function which requires HWnd as an argument. The handle of the newly created process can be obtained from the process ID by using enum Windows. A good implementation class has been provided here so you can use code like below to set focus to the window after creating the application:

DWORD pid = pi.dwProcessId;
CMainWindowIterator itw(pid);
for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next())
{
    SetFocus(hwnd);
    break;
}

Basic Key Presses

Now, let's say that you want to simulate the pressing of a key. You just have to use the function RunKey() like below:

VirKey vk; 
com="do";arg="TAB";times=2;sleep=300;

vk.RunKey(com,arg,times,sleep);

This function call will press, or more correctly simulate the pressing of, the key TAB twice in a 300 ms interval. The com parameter (character string) means the command you want to execute. Currently, two kinds of commands are implemented: "do" and "open". do can be used to to enter any key combination. open can be used to open any application.

Now, the arg parameter (character string) is in accordance with com. If com is do, then arg contains the code for a particular key, like TAB (an account of all keys supported along with their codes is given in the codes.txt file in the source code and binary release). If com is open, then arg is a character string containing the full path name of the application executable to be created, like, for IE, the default should be "C:\Program Files\Internet Explorer\IEXPLORE.EXE". If your path contains spaces in between, like the case above, then make sure that your path is specified in double quotes as shown above, as this is directly passed to the CreateProcess method. times (integer) specifies the number of times the do or open command has to be executed, and sleep (integer) denotes the time in msec between consecutive commands.

Converting a String into a Sequence of Key Presses

Now, if you want to send a string as a sequence of key presses and think that the previous function is also tedious, then this section may interest you. If your application requires entering a particular word, then you can use the Runstring() function as given below:

VirKey vk;
vk.Runstring("Hello You!!!");

The whole string will be converted into key presses. Caution: The string function will work with only standard characters and not with special keys like TAB, ALT etc.

Making Scripts

Now, this is the part from where the real fun starts. If you have a large task or key presses to perform, then you can use the script feature. Let's discuss the script first. The script is sequential in nature with an easy syntax. Each line in the script has four parts, similar to the parameters of the RunKey() above: command, argument, times, and sleep. The caution to maintain here is that argument should end with a $. For example, to open Internet Explorer and then to press Enter, your script would look like below:

open "C:\Program Files\Internet Explorer\IEXPLORE.EXE"$ 1 4000 
do  RETURN$  1  200

Along with the normal commands open and do, an additional command called string has been added. It can be used to enter strings:

string Hello!!$ 1 100

Now, when your script is prepared, you have to process it to prepare a file which contains the hexcode instead of key codes. This file is loaded, run-time interpreted, and run. This saves time and resources during running, and is similar to compilation and execution. To process a given script file, you can use the ES2S() function. This function takes two arguments (character strings): the source script file name and the script name. For example, to prepare the script hello from Scriptfile.txt, the function is called as:

VirKey vk;
vk.ES2S("Scriptfile.txt","hello");

Now, if your script is prepared, you might feel a strong urge to run it, in which case you have to use the Runx() function which takes as an argument the name of the script. Hence:

VirKey vk;
vk.Runx("hello");

Composite Key Presses

Your application might want to keep composite key combinations such as ALT+F4. For this purpose, support has been added for the composite key press of ALT, SHIFT, CTRL, and WIN. So, you just have to enter ALT+F4 as arg in the RunKey function or your script.

Caution: If you are planning to use 2-3 composite combinations like SHIFT+CTRL+DEL, then it will be a good idea to follow the order ALT, then CTRL, then SHIFT, then WIN. Like ALT+CTRL+f or CTRL+SHIFT+C etc. You should get the idea.

Application

A sample application has been provided as demo. Using the application is extremely easy. First, you have to prepare a script which you want to run. Let's say you want to open an Internet Explorer window and then automatically open Yahoo! mail and login into your account. Then, if you don't have any homepage set and have no proxy authentication while accessing the internet, your script should look like the one below:

open "C:\Program Files\Internet Explorer\IEXPLORE.EXE"$ 1 4000 
do TAB$ 1 200
string http://mail.yahoo.com$ 1 1000
do RETURN$ 1 4000
string username$ 1 100
do TAB$ 1 100
string password$ 1 100
do RETURN$ 1 200

After you prepare a script, save it in a file and open the application provided above. Click on "New Script File". A File Open dialog box will appear. Select your script file, and enter the name of the script by which you want it to run, e.g., "login". Then, press "Make Script"; your script will be processed .Then, enter the name you provided in the script, e.g., "login" in the first editor, and click on "Execute", and then don't touch your keyboard or mouse, and the script will start executing, opening an IE window, opening Yahoo!, and then logging in.

Conclusion

To conclude, if you would like to incorporate the class in your application, then just add Virkey.cpp, VirKey.h, WindowIterator.cpp, and WindowIterator.h in your code. I would like to thank Paul DiLascia for using his class for getting the process handle from the process ID, and also would like to sincerely apologize for the inhuman atrocities committed by me on the English language. If you find the class useful, then please feel free to drop your questions, suggestions, problems, and bugs at my mail address; otherwise, if the only thing you can think of are curses for me, then I am also searching for the moron who wrote this article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
Ankit is a Btech(IT) student studying at Indian Institute of Information Technology ,Allahabad, India ,likes to code in C/C++ and make useful utilities .In his free time he likes to listen to good music or watch good movies and he does not understands why everybody on this site writes about himself in third person

Comments and Discussions

 
GeneralScript explanation Pin
Anoop Tripathi6-Oct-08 0:41
Anoop Tripathi6-Oct-08 0:41 
GeneralRe: Script explanation [modified] Pin
Anoop Tripathi6-Oct-08 1:56
Anoop Tripathi6-Oct-08 1:56 
QuestionVB code? Pin
T Clancey28-May-08 2:00
T Clancey28-May-08 2:00 
GeneralGood idea, but bad coding Pin
SimonRa6-Aug-06 0:11
SimonRa6-Aug-06 0:11 
GeneralRe: Good idea, but bad coding Pin
Ankit Tandon6-Aug-06 7:46
Ankit Tandon6-Aug-06 7:46 
GeneralA bug in demo Pin
Homam Hosseini18-Mar-06 21:12
Homam Hosseini18-Mar-06 21:12 
GeneralRe: A bug in demo Pin
Ankit Tandon18-Mar-06 22:20
Ankit Tandon18-Mar-06 22:20 
GeneralRe: A bug in demo Pin
Homam Hosseini19-Mar-06 5:33
Homam Hosseini19-Mar-06 5:33 
GeneralRe: A bug in demo Pin
Ankit Tandon19-Mar-06 7:55
Ankit Tandon19-Mar-06 7:55 
Hi again
Its good to know that someone pays attenion to the crap i make and writeSmile | :) . Well you were correct both times about the bug.The fault has been identified and corrected(too idiotic to mention here). Now both ur cases are working correctly on my system.Pls check on urs and if could then pls confirm it.Also is the loop problem still there Confused | :confused: ???
Thx
Regards
Ankit

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.