2010-08-24 9 views
12

Nach einer wirklich tief bohren Sie die Web senden, dies ist mein Code, die leider tut die Schlüssel als Großbuchstaben an:/Kann nicht eine einzige Taste Funktion Remote-Desktop-

MapVirtualKey Umsetzung:

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

Send Umsetzung:

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

Nun zu den Methoden:

Diese Methode Schlüssel als Zeichenfolge senden, was in Ordnung durch den Remote-Desktop arbeiten:

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

diese Methode eine Taste drücken nach unten verwendet wird, , ursprünglich eingestellt auf:

down.Data.Keyboard.Scan = 0; 

, aber ich versuchte, die MapVirtualKey so bemerken die Änderung zu verwenden:

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

Und für die Prüfung:

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

auf meinem Konsolenfenster sehe ich: textabcABC textabcABC etc ...

auf dem RDC Konsolenfenster alles, was ich sehe, ist: Text Text etc ...

als ob die Single-Taste nicht funktioniert!

Wird viel jede Hilfe zu schätzen wissen! danke voraus, Niv.

+1

Ich bin wirklich Sie es versucht, zu helfen, aber ich brauche eine SSCCE (http://sscce.org/). Ich sehe dort eine Lösung für Ihr Problem, aber kann nicht mit unkompilierbarem Code helfen. – Bio42

+0

Vielleicht etwas in der Art von RunAsUser/CreateProcessAsUser – Theraot

+0

Was ist der Punkt der Überprüfung von "text.Length> UInt32.MaxValue/2"? Es ist immer wahr. – QtRoS

Antwort

0

Anstatt eine Zuordnung zu den Tastencodes vorzunehmen, sollten Sie die Zeichen einfach mit dem KEYEVENTF_UNICODE Flag senden. Nicht alle Zeichen sind als virtuelle Schlüssel darstellbar.

Durch das Senden einer LSHIFT wird der Tastaturstatus nicht aktualisiert. Wenn das Ziel überprüft, ob die Verschiebung gedrückt ist, wird der tatsächliche Status der Tastatur verwendet.

Ausgehend von Ihrer input.Data.Keyboard.Scan = 0 Zeile, es war einmal mit der entsprechenden Nachricht.

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 nicht einfach System.Windows.Forms.SendKeys.SendWait zu verwenden ("textabc"), es wird funktionieren