Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't send a single key function to remote desktop

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.

like image 374
Nivo Avatar asked Aug 24 '10 07:08

Nivo


1 Answers

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

like image 174
ansh shah Avatar answered Oct 20 '22 02:10

ansh shah