2010-08-24 3 views
12

Dopo un trapano davvero in profondità il web, questo è il mio codice che purtroppo inviare doesnt i tasti come maiuscolo:/Impossibile inviare una sola funzione chiave per desktop remoto

MapVirtualKey Implementazione:

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

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

Ora per i metodi:

Questo metodo invia chiavi come stringa, che funzionano bene attraverso il desktop remoto:

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

questo metodo viene utilizzato per premere un tasto , originariamente impostato su:

down.Data.Keyboard.Scan = 0; 

ma ho cercato di usare il MapVirtualKey quindi notare il cambiamento:

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

E per il test:

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

sulla mia finestra della console vedo: textabcABC textabcABC ecc ...

sulla finestra della console RDC tutto quello che vedo è: testo testo ecc ...

come se la singola chiave non funzioni!

Apprezzerò molto qualsiasi aiuto! grazie in anticipo, niv.

+1

che sto veramente cercando di aiutare a lì, ma ho bisogno di uno SSCCE (http://sscce.org/). Vedo lì una soluzione per il tuo problema ma non posso aiutarti con codice non compilabile. – Bio42

+0

Forse qualcosa sulla falsariga di RunAsUser/CreateProcessAsUser – Theraot

+0

Qual è il punto di controllo "text.Length> UInt32.MaxValue/2"? È sempre vero – QtRoS

risposta

0

Invece di mappare ai codici chiave, è sufficiente inviare i caratteri direttamente utilizzando il flag KEYEVENTF_UNICODE. Non tutti i caratteri sono rappresentabili come chiavi virtuali.

L'invio di uno LSHIFT non provoca l'aggiornamento dello stato della tastiera, quindi quando il target controlla se lo spostamento è premuto, viene utilizzato lo stato effettivo della tastiera.

Sulla base della linea input.Data.Keyboard.Scan = 0, in una sola volta, si stava utilizzando il messaggio appropriato.

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 non utilizzare semplici System.Windows.Forms.SendKeys.SendWait ("textabc") che funzionerà