无法将单个按键功能发送到远程桌面

时间:2010-08-24 07:07:54

标签: c# keyboard desktop sendinput

在深入钻取网页之后,这是我的代码,遗憾的是,它不会将密钥作为大写发送:/

MapVirtualKey实施:

    const uint MAPVK_VK_TO_VSC = 0x00;
    const uint MAPVK_VSC_TO_VK = 0x01;
    const uint MAPVK_VK_TO_CHAR = 0x02;
    const uint MAPVK_VSC_TO_VK_EX = 0x03;
    const uint MAPVK_VK_TO_VSC_EX = 0x04;

    [DllImport("user32.dll")]
    public static extern int MapVirtualKey(uint uCode, uint uMapType);

SendInput实施:

        struct INPUT
{
           public UInt32 Type;
           public MOUSEKEYBDHARDWAREINPUT Data;

}

  [StructLayout(LayoutKind.Explicit)]
struct MOUSEKEYBDHARDWAREINPUT
{
    [FieldOffset(0)]
    public MOUSEINPUT Mouse;

    [FieldOffset(0)]
    public KEYBDINPUT Keyboard;

    [FieldOffset(0)]
    public HARDWAREINPUT Hardware;
}


  [DllImport("user32.dll", SetLastError = true)]
    static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] inputs, Int32 sizeOfInputStructure);

现在的方法:

此方法将密钥作为字符串发送,通过远程桌面正常工作:

        public static void SimulateTextEntry(string text)
    {
        if (text.Length > UInt32.MaxValue / 2) throw new ArgumentException(string.Format("The text parameter is too long. It must be less than {0} characters.", UInt32.MaxValue / 2), "text");

        var chars = UTF8Encoding.ASCII.GetBytes(text);
        var len = chars.Length;
        INPUT[] inputList = new INPUT[len * 2];
        for (int x = 0; x < len; x++)
        {
            UInt16 scanCode = chars[x];

            var down = new INPUT();
            down.Type = (UInt32)InputType.KEYBOARD;
            down.Data.Keyboard = new KEYBDINPUT();
            down.Data.Keyboard.Vk = 0;
            down.Data.Keyboard.Scan = scanCode;
            down.Data.Keyboard.Flags = (UInt32)KeyboardFlag.UNICODE;
            down.Data.Keyboard.Time = 0;
            down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

            var up = new INPUT();
            up.Type = (UInt32)InputType.KEYBOARD;
            up.Data.Keyboard = new KEYBDINPUT();
            up.Data.Keyboard.Vk = 0;
            up.Data.Keyboard.Scan = scanCode;
            up.Data.Keyboard.Flags = (UInt32)(KeyboardFlag.KEYUP | KeyboardFlag.UNICODE);
            up.Data.Keyboard.Time = 0;
            up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

            // Handle extended keys:
            // If the scan code is preceded by a prefix byte that has the value 0xE0 (224),
            // we need to include the KEYEVENTF_EXTENDEDKEY flag in the Flags property. 
            if ((scanCode & 0xFF00) == 0xE000)
            {
                down.Data.Keyboard.Flags |= (UInt32)KeyboardFlag.EXTENDEDKEY;
                up.Data.Keyboard.Flags |= (UInt32)KeyboardFlag.EXTENDEDKEY;
            }

            inputList[2*x] = down;
            inputList[2*x + 1] = up;

        }

        var numberOfSuccessfulSimulatedInputs = SendInput((UInt32)len*2, inputList, Marshal.SizeOf(typeof(INPUT)));
    }

此方法用于按下一个键,其最初设置为:

    down.Data.Keyboard.Scan = 0;

但我尝试使用mapvirtualkey,因此请注意更改:

KeyPress:

  public static void SimulateKeyPress(VirtualKeyCode keyCode)
    {
        var down = new INPUT();
        down.Type = (UInt32)InputType.KEYBOARD;
        down.Data.Keyboard = new KEYBDINPUT();
        down.Data.Keyboard.Vk = (UInt16)keyCode;
       // down.Data.Keyboard.Scan = 0;
        ushort mapvirtualkeyresult = (ushort)(MapVirtualKey((UInt16)keyCode, MAPVK_VK_TO_CHAR));
        down.Data.Keyboard.Scan = mapvirtualkeyresult;
        down.Data.Keyboard.Flags = 0;
        down.Data.Keyboard.Time = 0;
        down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        var up = new INPUT();
        up.Type = (UInt32)InputType.KEYBOARD;
        up.Data.Keyboard = new KEYBDINPUT();
        up.Data.Keyboard.Vk = (UInt16)keyCode;
        //up.Data.Keyboard.Scan = 0;
        up.Data.Keyboard.Scan = (ushort)(MapVirtualKey((UInt16)keyCode, MAPVK_VK_TO_CHAR));
        up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
        up.Data.Keyboard.Time = 0;
        up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        INPUT[] inputList = new INPUT[2];
        inputList[0] = down;
        inputList[1] = up;

        var numberOfSuccessfulSimulatedInputs = SendInput(2, inputList, Marshal.SizeOf(typeof(INPUT)));
        if (numberOfSuccessfulSimulatedInputs == 0) throw new Exception(string.Format("The key press simulation for {0} was not successful.", keyCode));
    }

的KeyDown:

     public static void SimulateKeyDown(VirtualKeyCode keyCode)
    {
        var down = new INPUT();
        down.Type = (UInt32)InputType.KEYBOARD;
        down.Data.Keyboard = new KEYBDINPUT();
        down.Data.Keyboard.Vk = (UInt16)keyCode;
        down.Data.Keyboard.Scan = (ushort)(MapVirtualKey((UInt16)keyCode, MAPVK_VK_TO_CHAR));
        down.Data.Keyboard.Flags = 0;
        down.Data.Keyboard.Time = 0;
        down.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        INPUT[] inputList = new INPUT[1];
        inputList[0] = down;

        var numberOfSuccessfulSimulatedInputs = SendInput(1, inputList, Marshal.SizeOf(typeof(INPUT)));
        if (numberOfSuccessfulSimulatedInputs == 0) throw new Exception(string.Format("The key down simulation for {0} was not successful.", keyCode));
    }

KEYUP:

  public static void SimulateKeyUp(VirtualKeyCode keyCode)
    {
        var up = new INPUT();
        up.Type = (UInt32)InputType.KEYBOARD;
        up.Data.Keyboard = new KEYBDINPUT();
        up.Data.Keyboard.Vk = (UInt16)keyCode;
        up.Data.Keyboard.Scan = (ushort)(MapVirtualKey((UInt16)keyCode, MAPVK_VK_TO_CHAR));
        up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KEYUP;
        up.Data.Keyboard.Time = 0;
        up.Data.Keyboard.ExtraInfo = IntPtr.Zero;

        INPUT[] inputList = new INPUT[1];
        inputList[0] = up;

        var numberOfSuccessfulSimulatedInputs = SendInput(1, inputList, Marshal.SizeOf(typeof(INPUT)));
        if (numberOfSuccessfulSimulatedInputs == 0) throw new Exception(string.Format("The key up simulation for {0} was not successful.", keyCode));
    }

进行测试:

     int i=0;
           while (i<10)
           {
               Thread.Sleep(5000);
               InputSimulator.SimulateTextEntry("text");
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_A);
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_B);
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_C);
               InputSimulator.SimulateKeyDown(VirtualKeyCode.LSHIFT);
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_A);
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_B);
               InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_C);
               InputSimulator.SimulateKeyUp(VirtualKeyCode.LSHIFT);
               i++;
           }
我的控制台窗口上的

我看到: textabcABC textabcABC 等...

在rdc控制台窗口上的

我看到的是: 文本 文本 等...

好像单键按下不起作用!

非常感谢任何帮助! 谢谢你, 证:

2 个答案:

答案 0 :(得分:1)

Y不要使用简单的System.Windows.Forms.SendKeys.SendWait(“textabc”)它会起作用

答案 1 :(得分:0)

您应该使用KEYEVENTF_UNICODE标志直接发送字符,而不是映射到键代码。并非所有字符都可以表示为虚拟键。

发送LSHIFT不会导致键盘状态更新,因此当目标检查是否按下shift时,会使用键盘的实际状态。

基于您的input.Data.Keyboard.Scan = 0行,它一次使用了相应的消息。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        #region P/Invokes

        struct INPUT
        {
            public INPUTType type;
            public INPUTUnion Event;
        }

        [StructLayout(LayoutKind.Explicit)]
        struct INPUTUnion
        {
            [FieldOffset(0)]
            internal MOUSEINPUT mi;
            [FieldOffset(0)]
            internal KEYBDINPUT ki;
            [FieldOffset(0)]
            internal HARDWAREINPUT hi;
        }

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

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

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

        enum INPUTType : uint
        {
            INPUT_KEYBOARD = 1
        }

        [Flags]
        enum KEYEVENTF : uint
        {
            EXTENDEDKEY = 0x0001,
            KEYUP = 0x0002,
            SCANCODE = 0x0008,
            UNICODE = 0x0004
        }

        [DllImport("user32.dll", SetLastError = true)]
        static extern UInt32 SendInput(int numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);

        private static void Send(string s)
        {
            foreach (var c in s)
                Send(c);
        }

        private static void Send(char c)
        {
            SendKeyInternal((short)c);
        }

        #endregion

        private static void SendKeyInternal(short key)
        {
            // create input events as unicode with first down, then up
            INPUT[] inputs = new INPUT[2];
            inputs[0].type = inputs[1].type = INPUTType.INPUT_KEYBOARD;
            inputs[0].Event.ki.dwFlags = inputs[1].Event.ki.dwFlags = KEYEVENTF.UNICODE;
            inputs[0].Event.ki.wScan = inputs[1].Event.ki.wScan = key;    
            inputs[1].Event.ki.dwFlags |= KEYEVENTF.KEYUP;

            uint cSuccess = SendInput(inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
            if (cSuccess != inputs.Length)
            {
                throw new Win32Exception();
            }
        }

        static void Main(string[] args)
        {
            System.Threading.Thread.Sleep(3000);
            Send("Hello world!");
        }
    }
}