Can't send a single key function to remote desktop

空扰寡人 提交于 2021-02-17 21:43:19

问题


After a really deep drill down the web, this is my code which unfortunately doesnt send the keys as upper case :/

MapVirtualKey Implementation:

    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 Implementation:

        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);

Now for the methods:

This method send keys as string, which work fine through the remote desktop:

        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)));
    }

this method is used to press down a key, its originally set to:

    down.Data.Keyboard.Scan = 0;

but i tried to use the mapvirtualkey so notice the change:

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));
    }

And for the testing:

     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++;
           }

on my console window i see: textabcABC textabcABC etc...

on the rdc console window all i see is: text text etc...

as if the single key press doesnt work!

Will Much appreciate any help! thanks ahead, Niv.


回答1:


Y not to use simple System.Windows.Forms.SendKeys.SendWait("textabc") it will work




回答2:


Instead of mapping to key codes, you should just send the characters directly using the KEYEVENTF_UNICODE flag. Not all characters are representable as Virtual Keys.

Sending a LSHIFT does not cause the keyboard state to get updated, so when the target checks whether shift is depressed, the actual state of the keyboard is used.

Based off of your input.Data.Keyboard.Scan = 0 line, at one time, it was using the appropriate message.

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!");
        }
    }
}


来源:https://stackoverflow.com/questions/3554171/cant-send-a-single-key-function-to-remote-desktop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!