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.