C++调用SendInput()传入字符串报错,已转用C#开发求助
Hey there! I see you switched from C++ to C# to build your keystroke sender, but ran into issues with SendInput—that makes sense because C# doesn't have a built-in SendInput that takes a string directly like you might have hoped. Let's fix this step by step.
First, the core problem: Windows' SendInput API works with low-level input structures, not raw strings. We need to convert each character in your message into a sequence of key press/release events, including handling modifiers like Shift for uppercase letters or symbols.
Step 1: Declare the Windows API Structures and Functions
First, we need to set up the P/Invoke declarations for the Windows APIs we'll use (SendInput and VkKeyScan). Add these at the top of your class:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; public class KeySender { // Constants for input types private const int INPUT_KEYBOARD = 1; private const int KEYEVENTF_KEYUP = 0x0002; // Structures required for SendInput [StructLayout(LayoutKind.Sequential)] private struct INPUT { public int type; public KEYBDINPUT ki; } [StructLayout(LayoutKind.Sequential)] private struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } // P/Invoke declarations [DllImport("user32.dll", SetLastError = true)] private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern short VkKeyScan(char ch); }
Step 2: Create a Method to Convert String to Keystrokes
Next, add a method that takes your string and converts it into an array of INPUT structures. This method will handle each character, check if Shift is needed, and create press/release events:
private static INPUT[] CreateKeyInputs(char ch) { var inputs = new List<INPUT>(); short keyData = VkKeyScan(ch); // Extract virtual key code and shift state from the result ushort vk = (ushort)(keyData & 0xFF); bool needShift = ((keyData >> 8) & 0x1) == 1; // Press Shift first if the character requires it if (needShift) { inputs.Add(CreateKeyInput(0x10, false)); // VK_SHIFT = 0x10 } // Simulate pressing the character key inputs.Add(CreateKeyInput(vk, false)); // Simulate releasing the character key inputs.Add(CreateKeyInput(vk, true)); // Release Shift if we pressed it earlier if (needShift) { inputs.Add(CreateKeyInput(0x10, true)); } return inputs.ToArray(); } private static INPUT CreateKeyInput(ushort vk, bool isKeyUp) { return new INPUT { type = INPUT_KEYBOARD, ki = new KEYBDINPUT { wVk = vk, dwFlags = isKeyUp ? KEYEVENTF_KEYUP : 0, dwExtraInfo = IntPtr.Zero } }; }
Step 3: Update Your Main Logic to Send the String
Now replace your original SendInput(message) call with code that iterates over each character and sends the corresponding inputs. Also note that in C#, we use Console.ReadLine() instead of getline(cin, message):
public static void SendString(string message) { foreach (char ch in message) { INPUT[] inputs = CreateKeyInputs(ch); SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT))); // Optional: Small delay between characters to mimic real typing behavior Thread.Sleep(50); } } // In your main program flow: public static void Main() { string message; Console.WriteLine("Enter the message to send:"); message = Console.ReadLine(); SendString(message); }
Quick Notes
- Why the delay? Adding a small
Thread.Sleepbetween characters helps prevent issues with applications that can't process keystrokes too quickly (just like how a human types). - Special characters:
VkKeyScanhandles most common alphanumeric and symbol characters, but for more complex keys (like function keys or media controls), you'll need to use their specific virtual key codes directly. - Error handling: You can add checks for the return value of
SendInput(it returns the number of inputs successfully sent) to debug any issues with failed keystrokes.
That should get your keystroke sender working properly in C#!
内容的提问来源于stack exchange,提问作者Koi

