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

发布于 2024-09-15 13:36:29 字数 7257 浏览 7 评论 0原文

经过对网络的深入研究后,这是我的代码,不幸的是,它没有以大写形式发送密钥:/

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

在我的控制台窗口上我看到: 文本abcABC 文本abcABC 等等......

在rdc控制台窗口上我看到的是: 文本 文本 等等...

好像单键按下不起作用!

非常感谢任何帮助! 在此先感谢, 尼布。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小帐篷 2024-09-22 13:36:29

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

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

浅忆流年 2024-09-22 13:36:29

您应该使用 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!");
        }
    }
}

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!");
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文