DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • 4 Email Validation and Verification Techniques for App Developers
  • What Are Microservices Architecture and How Do They Work?
  • Microsoft Azure Active Directory
  • Build Your Own AI Avatar App From Scratch in Less Than 8 Hours

Trending

  • How To Verify Database Connection From a Spring Boot Application
  • Java Parallel GC Tuning
  • Unleashing the Power of Microservices With Spring Cloud
  • A Better Web3 Experience: Account Abstraction From Flow (Part 2)
  1. DZone
  2. Data Engineering
  3. Databases
  4. Sending Keystrokes to Other Apps with Windows API and C#

Sending Keystrokes to Other Apps with Windows API and C#

Recently I had to tackle a task where I needed to send keystrokes to another application, that are initiated from a .NET Windows app.

Denzel D. user avatar by
Denzel D.
·
Feb. 01, 13 · Tutorial
Like (1)
Save
Tweet
Share
43.92K Views

Join the DZone community and get the full member experience.

Join For Free

Recently I had to tackle a task where I needed to send keystrokes to another application, that are initiated from a .NET Windows app. Obviously, there is a way to do it through WinAPI, and the way is called SendInput - a core function that can be used to simulate key presses, mouse actions and button clicks.

Let's talk about what's needed. First of all, you are using it to send keystrokes, and not characters, to wherever the current input focus is located. So, for example, if I would want to print the { symbol on the screen, I would not be able to just get it's code representation because the actual key that carries it on a standard US QWERTY keyboard would be [. The problem that I've seen happen more than once is a developer attempting to leverage VkKeyScan to get the necessary virtual-key code to replicate it later, it producing another character instead.  

Now let's look at the native signature for it:


UINT WINAPI SendInput(
  _In_  UINT nInputs,
  _In_  LPINPUT pInputs,
  _In_  int cbSize
);

In the constraints of a managed environment, in my case - in a C# application, this declaration would look like this:


[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

Remember, since you are using P/Invoke, you need to add a 


public struct INPUT
{
    public int type;
    public InputBatch u;
}

What exactly is InputBatch? If you look at the INPUT structure layout, you will notice that it relies on a union of MOUSEINPUT, KEYBDINPUT and HARDWAREINPUT - structs that are carrying data related to their own class of input simulation. A basic implementation of those in C# looks like this:


[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
    public int dx;
    public int dy;
    public uint mouseData;
    public uint dwFlags;
    public uint time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{    
    public ushort wVk;
    public ushort wScan;
    public uint dwFlags;
    public uint time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
    public uint uMsg;
    public ushort wParamL;
    public ushort wParamH;
}


In our case, we are focusing on the keyboard, so let's go through the fields that we're using in the KEYBDINPUT struct.

  • wVk - the virtual key code. Not the same as the character code. You can find a list of virtual key codes 

  • wScan - the hardware scan code (read the spec here).

  • dwFlags - complementary flags that pre-determine input processing behavior. You can find the complete list on MSDN.
  • time - unless you need to specify a different timestamp, let Windows provide its own and set the value to 0.
  • dwExtraInfo - will be associated with a call to GetMessageExtraInfo.

Let's assume that I want to simulate the Enter key press. To do this, I first need to generate an array of INPUT structs that would act as the input descriptor:


WindowsAPI.INPUT[] data = new WindowsAPI.INPUT[] {
    new WindowsAPI.INPUT() 
    {
        type = WindowsAPI.INPUT_KEYBOARD,
        u = new WindowsAPI.InputBatch
        {
            ki = new WindowsAPI.KEYBDINPUT
            {
                wVk = 0x0D,
                wScan = 0,
                dwFlags = 0,
                dwExtraInfo = WindowsAPI.GetMessageExtraInfo(),
            }
        }
    } 
};

Notice that I am using the HEX representation for Enter (that's the proper associated virtual-key code). When I want to invoke SendInput, I can call this:


WindowsAPI.SendInput((uint)data.Length, data, Marshal.SizeOf(typeof(WindowsAPI.INPUT)));

Marshal.SizeOf will return the value for the size of the INPUT struct. What happens if I need to send a key combination? This is easily implemented through multiple INPUT instances. For example, for Ctrl+F5 you could use this:


public static WindowsAPI.INPUT[] Find()
{
    WindowsAPI.INPUT[] data = new WindowsAPI.INPUT[] {
        new WindowsAPI.INPUT() 
        {
            type = WindowsAPI.INPUT_KEYBOARD,
            u = new WindowsAPI.InputBatch
            {
                ki = new WindowsAPI.KEYBDINPUT
                {
                    wVk = 0xA2,
                    wScan = 0,
                    dwFlags = 0,
                    dwExtraInfo = WindowsAPI.GetMessageExtraInfo(),
                }
            }
        },
        new WindowsAPI.INPUT() 
        {
            type = WindowsAPI.INPUT_KEYBOARD,
            u = new WindowsAPI.InputBatch
            {
                ki = new WindowsAPI.KEYBDINPUT
                {
                    wVk = (ushort)WindowsAPI.VkKeyScan('f'),
                    wScan = 0,
                    dwFlags = 0,
                    dwExtraInfo = WindowsAPI.GetMessageExtraInfo(),
                }
            }
        }    
    };

    return data;
}

Afterwards, call SendInput the same way as you called it for the Enter key. There is one problem here, though. As you are going to call this function, you will notice that the OS will still consider the Ctrl key pressed. To avoid this, you would need to use a KEYBDINPUT instance with dwFlags for set to KEYEVENTF_KEYUP to release the key.

API app

Opinions expressed by DZone contributors are their own.

Related

  • 4 Email Validation and Verification Techniques for App Developers
  • What Are Microservices Architecture and How Do They Work?
  • Microsoft Azure Active Directory
  • Build Your Own AI Avatar App From Scratch in Less Than 8 Hours

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: