2010-08-24 25 views
12

Sau một thực sự sâu khoan xuống các trang web, đây là mã của tôi mà tiếc doesnt gửi các phím như chữ hoa:/Không thể gửi một chức năng quan trọng duy nhất để remote desktop

MapVirtualKey Thực hiện:

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 Thực hiện:

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

Bây giờ cho các phương pháp:

Phương pháp này gửi các phím như chuỗi, mà làm việc tốt thông qua các máy tính để bàn từ xa:

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

phương pháp này được sử dụng để nhấn xuống một chìa khóa , thiết lập ban đầu của nó là:

down.Data.Keyboard.Scan = 0; 

nhưng tôi cố gắng sử dụng mapvirtualkey nên chú ý đến sự thay đổi:

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

Và đối với việc thử nghiệm:

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

trên cửa sổ giao diện điều khiển của tôi tôi thấy: textabcABC textabcABC vv ...

trên cửa sổ RDC console tất cả tôi thấy là: văn bản văn bản vv ...

như thể nhấn phím đơn không hoạt động!

Sẽ đánh giá cao mọi trợ giúp! cảm ơn trước, Niv.

+1

Tôi đang thực sự cố gắng để giúp bạn có nhưng tôi cần một SSCCE (http://sscce.org/). Tôi thấy có giải pháp cho vấn đề của bạn nhưng không thể trợ giúp với mã không thể giải mã được. – Bio42

+0

Có thể một cái gì đó dọc theo dòng RunAsUser/CreateProcessAsUser – Theraot

+0

Điểm kiểm tra "text.Length> UInt32.MaxValue/2" là gì? Nó luôn luôn đúng. – QtRoS

Trả lời

0

Thay vì ánh xạ tới mã khóa, bạn chỉ cần gửi các ký tự trực tiếp bằng cờ KEYEVENTF_UNICODE. Không phải tất cả các ký tự đều được thể hiện dưới dạng Khóa ảo.

Gửi LSHIFT không làm cho trạng thái bàn phím được cập nhật, vì vậy khi mục tiêu kiểm tra xem có thay đổi hay không, trạng thái thực tế của bàn phím được sử dụng.

Dựa trên dòng input.Data.Keyboard.Scan = 0 của bạn, cùng một lúc, nó đang sử dụng thông báo thích hợp.

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

Y không sử dụng System.Windows.Forms.SendKeys.SendWait đơn giản ("textabc") nó sẽ làm việc

Các vấn đề liên quan