Prevent / stop windows system entering idle state, prevent system idle time in win32api program using GetLastInputInfo, keybd_event, windowless timers

Introduction

This article is about preventing the windows computer system going to idle state using win32 api program. The window system idle time is the elapsed time when there is no keyboard input or mouse input or other input system. That is when there is no input form the user through keyboard, mouse or other input devices the system maintains a counter and if that counter reaches some seconds then the system goes to an idle state. If there is any input from the user then this counter resets. So each time the system receives any input the counter resets to zero. The no of seconds after which the system goes idle is the idle time which can be defined in the control panel. But some times even if you had disables this option in the control panel the system goes idle. Or you will not have access to modify this setting in control panel. Hence this program which will prevent the system going to idle state by generating keyboard input automatically for every 20 seconds if the system is in an idle state in a windowless window application. This program uses three functions. They are GetLastInputInfo, keybd_event, settimer functions in a windowless win32 application.

I wanted to write my own program and read the documentation and sample code. I used an existing code which demonstrated how to get the idle time of windows. And wrote my own windowless timer and keybd_event to trigger keystrokes. and if you guys have more idea which will enhance or i am missing then please post in the comments section.

Find windows system idle time using GetLastInputInfo function

As mentioned, the idle time is the elapsed time when there is no input from the user. From the keyboard, mouse or other input devices. This elapsed time is reset with there is an input. So the counter starts from zero and keeps ticking (incrementing) if there is no input. After it reaches a specified max time then the system goes idle state. But if there in input from the user then again it starts from zero and increments. You can set the idle time in the control panel or you can set that the system not to go to idle time.

void getidle()
{                      
    LASTINPUTINFO info; 
    info.cbSize = sizeof(info);
    GetLastInputInfo(&info);
    DWORD idleSeconds = (GetTickCount() - info.dwTime)/1000;
    previous = idleSeconds;

    //if(previous > 20)press();

}

Previous is a global variable which holds the elapsed time using which you can find how long the system has been in idle state. according to your condition like i have you can call certain functions to do a task.

So what i am doing here is i have set a timer which will call this function each 20 seconds (which i have described below). And in this function i am checking whether previous is 20 which means 20 seconds. if so i call a function press. That will send a keystroke to the system as if the user has pressed the key. I have explained it below.


Send keystroke using keybd_event function

Assuming that system is idle for 20 seconds we can use keybd_event function to send a keystroke. I have used numlock for my purpose. Any other keystroke would conflict with your current mouse or typing event so i used numlock. Why the need to call keybd_event four times? i have explained below the code.

void press()
{
      // Simulate a key press
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | 0,
                      0 );

      // Simulate a key release
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
                      0);
                      
      // Simulate a key press
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | 0,
                      0 );

      // Simulate a key release
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
                      0);                      
}

Usually when we press a key we do two actions in that one is press event and other is release event. So we are calling keybd_event twice so that we make a press and release event. If you just call it once then you are making the key pressed. This state is equal to pressing and holding a key and not releasing it. So, you have to call the function second time with additional parameter to make the key released. So by sending the first function call you say to the system that you are pressing the key and by calling second time you are saying that you have released the key. Note that the second call's use additional parameter KEYEVENTF_KEYUP to specify that it is a call to release the key

BUT WHY 4 TIMES? It is because i am using numlock. Assume numlock is off. Press and release will on it. But i want to leave numlock in its original state. So i am issuing again a press and release. So if it is off then on and off. if it is on then off and on. so 4 times.


Windowless timer

We have seen code to find idle time and send keystroke. Now we will make a program which will not have any window, no window class definition, no window procedure and just a plain simple program which will run at the background without a window. Besides, we will use timers to call getidle function.

For more information about windowless timers look into this which has external references to the same resource

int main()
{

    SetTimer(NULL, 1, 20000, (TIMERPROC) getidle);
    MSG msg;


    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

Just define a main function with or without argc and argv. use the SetTimer function to set the callback function and to set the time interval at which the callback function should be called.

Here i have mentioned 20 which mean 20 seconds. So the settimer function will call getidle every 20 seconds. And whenever the getidle function is called it will do the work as stated above sections and so do the press function.

The message loop is the best way to make the control wait for a message instead of CPU consuming infinite while loops which will take more cpu resource. The reason for specifically using a message loop is stated in this link and in its reference links.

Complete source code

Here is the complete source code i have used to create an executable. It has no dependency. I mean you dont have to include extra libraries to compile this program.

#include 

void getidle();
void press();

DWORD previous = 0;

//int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
int main()
{

    SetTimer(NULL, 1, 20000, (TIMERPROC) getidle);
    MSG msg;


    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

//void getidle(HWND hwnd, UINT ui, INT i, DWORD dw)
void getidle()
{                      
    LASTINPUTINFO info; 
    info.cbSize = sizeof(info);
    GetLastInputInfo(&info);
    DWORD idleSeconds = (GetTickCount() - info.dwTime)/1000;
    previous = idleSeconds;

    if(previous > 20)press();    
}


void press()
{
      // Simulate a key press
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | 0,
                      0 );

      // Simulate a key release
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
                      0);
                      
      // Simulate a key press
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | 0,
                      0 );

      // Simulate a key release
         keybd_event( VK_NUMLOCK,
                      0x45,
                      KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
                      0);
                      
}


Points to Note:

I have compiled this code using Dev-C++ IDE and mingw compiler. Windows 7. It worked well for me. and is working well as expected. I haven't tested it in other environments. If there is anything missing in this code then please comment it so that me and the world would update that information. So please feel free to post your comments. The file size ie less than 1MB and appriximately 19KB.

Download Executable as zip

This executable was created in a very secure environment and has been uploaded to the server from the same environment with the details stated in the points to note section.

NOTE: For security reasons after downloading better scan the file before using it either using installed antivirus or using online antivirus checker for single files. Browsers warn you when you download executables which is not downloaded much from the internet. If you are scared then better compile the code yourself.
Click here to download no-idle application

That is all folks. Enjoy.

By -

Comments, Suggestions, Objections, ...