Chrome remote desktop Console.ReadKey yelds System.ConsoleKey.Packet instead of keystroke - c#

This is more of a curiosity to be completely honest.
Inside a console project I am developing I request input from the user in a looped form of this:
ConsoleKey response;
Console.Write("Write messages to log? [y/n] ");
response = Console.ReadKey(false).Key;
assume 4 cases:
case 1: Pressing the 'y' key on a keyboard directly atached to the pc running the software.
case 2: Connecting from another computer trough remote desktop connection and pressing the 'y' key on that machine.
case 3: Using on screen keyboard and press the 'y' key trough clicking on it (remotely or locally had no difference)
case 4: Connecting from another machine (specifically a phone) trough chrome remote desktop and pressing the 'y' key.
In case 1, 2 and 3, 'response' will contain 'Y'.
In case 4 'response' will instead contain System.ConsoleKey.Packet aka enum 231 PACKET key (used to pass Unicode characters with keystrokes).
I have tried the same thing trough a second pc and I noticed this behavior does not appear to occurr.
The most interesting thing is that the console shows me this
Write messages to log? [y/n] y
From this I evince that the keystroke is indeed received but handled incorrectly by my code.
I am at a loss as to how to proceed.
Console.ReadLine yelds the correct keystrokes but i would prefer to use Console.ReadKey if possible.
Is this specific behavior for phone keyboards? How would I obtain the actual key?

How would I obtain the actual key?
The MSDN docs for ConsoleKey.Packet doesn't say anything useful, so I found references to ConsoleKey in the source which lead here. That's casting ir.keyEvent.virtualKeyCode to a ConsoleKey where ir is an InputRecord.
A quick google finds the WinApi equivalent is INPUT_RECORD, and chasing the docs through KEY_EVENT_RECORD leads to this doc of Virtual-Key codes, which contains some more docs for VK_PACKET:
Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
The Remarks for KEYBDINPUT say:
INPUT_KEYBOARD supports nonkeyboard-input methods—such as handwriting recognition or voice recognition—as if it were text input by using the KEYEVENTF_UNICODE flag. If KEYEVENTF_UNICODE is specified, SendInput sends a WM_KEYDOWN or WM_KEYUP message to the foreground thread's message queue with wParam equal to VK_PACKET. Once GetMessage or PeekMessage obtains this message, passing the message to TranslateMessage posts a WM_CHAR message with the Unicode character originally specified by wScan. This Unicode character will automatically be converted to the appropriate ANSI value if it is posted to an ANSI window.
From my searching it doesn't look like .NET implements this mechanism for you, so you might have to do it yourself!
I'm afraid I've no idea why it's happening in your case however...

I just ran into this issue too! In my case, it only happened when connecting to my development pc from a phone as well. (I was using the RDP app)
Here's what I came up with today that works!
public static bool Confirm(string prompt)
{
Console.Write($"{prompt} [y/n] ");
char letter;
do
{
letter = char.ToLower(Console.ReadKey(true).KeyChar);
} while (letter != 'y' && letter != 'n');
Console.WriteLine(letter);
return letter == 'y';
}
Thanks for confirming that I'm not the only one with the issue!

Related

.Net TCP/IP send character with Ctrl Key modifier

I am interfacing with a piece of hardware via a TCP/IP socket, however the documentation is limited.
At present I can get the response I am after by sending Ctrl+G in Putty which prints as '^G'
How can i replicate this in code? I can send 'G' but I'm not sure how to modify it with 'Ctrl'
Dim buffer = Text.ASCIIEncoding.ASCII.GetBytes(cmd & vbNewLine)
ns.Write(buffer, 0, buffer.Length) 'ns = Network Stream
ns.Flush()
I am working in VB.Net however examples in C# are fine.
The Ctrl button isn't actuall sent, the Ctrl button + a character acts as a shortcut to a number of ASCII control charachters. In this case Ctrl+G sends the (ASCII value 007) control character (printed as ^G)
https://en.wikipedia.org/wiki/Control_character#In_ASCII

redirect input from keyboard like device to background process in windows environment

I use simple RFID reader device which connected to PC with usb cable and identified as keyboard like device.
I want to read input from this device by my application but it is running in background i.e. other application is in focus.
How can I redirect stdin to my application in windows 7 environment?
I can't change focus to my application
I can't make change in front application (e.g. catch stdin and send it to my application via pipe etc.)
My application is written in C# but I can rewrite it to Java / C
The PC runs Win 7 OS.
Thanks
y
Here my solution:
I have connected a normal Keyboard and a Card Reader via USB to my computer.
Both devices write to the windows keyboard buffer.
I want to redirect the input of the Card Reader to another application or file and remove it from the keyboard buffer (so that this input will not show up in any editor).
What I know / Prerequisites:
The input of the Card Reader only contains hexadecimal letters (0-9, A-F) and is finished by a newline.
The Card Reader input will be received "on-block", this means between two received letters there are only a few milliseconds
It is not possible for a human to enter two or more numbers within less than 70ms(I have tried it)
What I do:
I listen to the keyboard buffer and take out every single input letter/key. Any input which is not 0-9 or A-F will be put back to the keyboard buffer immediately.
If a input 0-9 or A-F comes up I will store it in a string buffer (it might be from the card reader)
If there is no further input for more than 70ms and there are at least 4 Bytes containing 0-9 or A-F in the buffer, then I assume/know it was from the Card Reader and use it in my own way. These Bytes have been already taken out of the keyboard buffer.
If there are only one/two/three letter(s) 0-9/A-F in my buffer, then after 70ms they will be put back to the windows keyboard buffer. While typing you can't realise that "some" letters show up a little postponed for a human being.
Here my program (written in the script language AutoHotkey):
KeybRedir.ahk
; KeybRedir
; Programmiert von Michael Hutter - Mai 2018
#NoEnv ;Avoids checking empty variables to see if they are environment variables
#SingleInstance force
Process, Priority, , Normal
#Warn All
SaveKeyList=
0::
1::
2::
3::
4::
5::
6::
7::
8::
9::
+A::
+B::
+C::
+D::
+E::
+F::
Return::
{ ; If one of these characters was typed => take it out of windows key buffer...
if A_ThisHotkey = Return
Hotkey:=Chr(13)
else
Hotkey:=A_ThisHotkey
SaveKeyList = %SaveKeyList%%Hotkey%
SetTimer , DoKeyPlay, 70 ; Wait 70ms for another key press of charlist (re-trigger the timer in case it already runs)
}
return
DoKeyPlay:
SetTimer , , Off
SaveText:=RegExReplace(SaveKeyList, "\+", "")
StringReplace, SaveText, SaveText, `r, , All
if StrLen(SaveText) < 4 ; Accumulated text size < 4 letters => normal key input
{
SendPlay %SaveKeyList% ; put captured text back in windows key buffer
}
else ; Now we have the input of the card reader
{
SplashTextOn, , , %SaveText% ; Do something with the input or the card reader ...
}
SaveKeyList=
SaveText=
SetTimer , SplashOff, 2000
return
SplashOff:
SplashTextOff
SetTimer , , Off
return
You can compile this script to a exe file (327KB) using the Autohotkey Compiler.

How to send Keys to an application

I have a very basic problem, For a game (Dota 2) I want to write a little macro which opens the console, writes "setinfo name ".........................."" into it and then closes it, the hotkey for console is set to '#'. For this I wrote an application which listens for the key 'f' to be pressed, and then send
1) '#' (open the console)
2) "messag ebla bla b...."
3) '#' (close the console)
everything is working except that it will not open the console (but if the console is already open it will write #messagej.j....# into it when i press f just as wanted)
my code for sending the keys.
SendKeys.Send("#");
SendKeys.Send("my message for consol");
SendKeys.Send("#");
does anybody know why the hotkeys dont work by sending keys? I thought its an simulation of when the user presses F or Q.
First thing You should try is adding a "software" delay between keypresses.
string MSG = "#yourmessage#";
foreach (object c_loopVariable in MSG) {
c = c_loopVariable;
Sendkeys.Send(c);
sleep(20);
}
The other thing to consider - sendkeys do not emulate the keypress at the hardware layer - it is on windows API level, and the DirectX DirectInput., witch most games use for user input processing goes a level further. So it is possible You will not be able to do it this easy.
You should check out more of keybd_event. Ive had better luck using that - as i understand it goes a level deeper than just sendkeys.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx
Anyways, I hope u are not going to use this for some spamming in a great game! :)

Simulate KeyPress in C# to Game

I'm trying to simulate a keypress into another window, which is a game. The things that don't work are:
SendKey - Send the input as strings like some text or something but doesn't go for ENTER TAB or other critical keys
InputSimulator - Complete waste of time
SendInput - Have some problems with this as well. It doesn't compile, and I've never used it before
PostMessage - it seems these 2 are pretty much the same and again they do send text but again no other keys such as ENTER TAB or other. Also couldn't figure out the value for wParam if i wanna hold down the key for a number of seconds. It is a 32bit Hex value in which seems the last 16 are repetition number.
SendMessage - See PostMessage
AUTOIT or AHK it seems that they have troubles being incorporated into C# if anyone knows how to do that, it would help immensely, this meaning I'd be able to write AHK script in the C# .cs file so it would compile. COM, ref, or anything.
Having problems with DirectInput
public void Test_KeyDown()
{
INPUT[] InputData = new INPUT[2];
Key ScanCode = Microsoft.DirectX.DirectInput.Key.W;
InputData[0].type = 1; //INPUT_KEYBOARD
InputData[0].ki.wScan = (short)VirtualKeyCode.NUMPAD2 ; //ScanCode;
InputData[0].ki.dwFlags = (int)KEYEVENTF.SCANCODE;
InputData[1].type = 1; //INPUT_KEYBOARD
InputData[1].ki.wScan = (short)VKeys.VK_W;
InputData[1].ki.dwFlags = (int)(KEYEVENTF.KEYUP | KEYEVENTF.UNICODE);
// send keydown
if (SendInput(2, InputData, Marshal.SizeOf(InputData[1])) == 0)
{
System.Diagnostics.Debug.WriteLine("SendInput failed with code: " +
Marshal.GetLastWin32Error().ToString());
}
}
It gives this error:
Could not load file or assembly 'Microsoft.DirectX.DirectInput.dll' or one of
its dependencies. is not a valid Win32 application.
(Exception from HRESULT: 0x800700C1)
I've referenced it from DirectX SDK tool kit 2007
I'm trying to send a key to another instance or handle. C++ or C# anything that works is fine, too.
Looks like you are trying to load a 32bit dll in a 64 bit solution, so please use the 64bit dll

How can I read barcodes without having the user focus a text box first?

I recently acquired a Metrologic Barcode scanner (USB port), as everyone already knows it works as a keyboard emulator out of the box.
How do I configure the scanner and my application so that my app can process the barcode data directly? That is, I don't want the user to focus on a "Text field" and then process the data when the KeyPress event fires.
Usually barcode scanners can be configured to send some characters before and after the string. So if you append eg "F12" before the barcode string, you can capture that and move the focus to the right field.
Check the barcode scanner manual how to do that.
Although your barcode has a USB connector. It can be programmed as a Keyboard wedge or RS232.
See this page http://www.instrumentsandequipmentco.com/support/faq-metrologic.htm
Where it says
Q. What is the difference between USB Keyboard and USB Point-of-Sale?
When the MX009 is set-up to communicate as a USB Keyboard, the scanned data will appear in the current application that is active on your PC. The data is entered just as if the keys were pressed on the keyboard. When the MX009 is set-up to communicate as a USB Point-of-Sale device, the data is transmitted to the USB port like RS232 data and the USB port must be configured like a COM port. The MX009 leaves the factory set for either USB Keyboard or USB Point-of-Sale.
When your program accepts RS232 you no longer need focus in a text field.
Reprogram your barcode as Point-of-Sale (RS232)
Reprogram to send a suffix usually - carriage-return/CR/$0D at the end of the barcode.
Look for the Carriage return to know when the complete barcode is available to your code.
I would guess the easiest way to do this would be to intercept key-presses at a higher level, such as PreviewKeyDown in winforms (or use KeyDown on the form, set KeyPreview to true, and use e.SuppressKeyPress to stop the key going down to the controls). There might be a direct API to the device; there might not.
You can use the OnShortcut event on a form to intercept keyboard presses.
Check if the prefix you configured on the barcodescanner appears, and set as Handled al keypresses until you get the barcode scanner suffix.
Within your Shortcut handler build up the barcode string
The following code is adapted from something I use myself, but is untested in its current form.
// Variables defined on Form object
GettingBarcode : boolean;
CurrentBarcode : string;
TypedInShiftState: integer; // 16=shift, 17=ctrl, 18=alt
procedure Form1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
var
Character:Char;
begin
Character:=Chr(MapVirtualKey(Msg.CharCode,MAPVK_VK_TO_CHAR));
if GettingBarcode then
begin
// Take care of case
if (TypedInShiftState<>16) and CharInSet(Character,['A'..'Z']) then
Character:=Chr(Ord(Character)+32);
TypedInShiftState:=0;
// Tab and Enter programmed as suffix on barcode scanner
if CharInSet(Character,[#9, #13]) then
begin
// Do something with your barcode string
try
HandleBarcode(CurrentBarcode);
finally
CurrentBarcode:='';
Handled:=true;
GettingBarcode:=False;
end;
end
else if CharInSet(Character,[#0..#31]) then
begin
TypedInShiftState:=Msg.CharCode;
Handled:=True;
end
else begin
CurrentBarcode:=CurrentBarcode+Character;
Handled:=true;
end;
end
else begin
if Character=#0 then
begin
TypedInShiftState:=Msg.CharCode;
end
else if (TypedInShiftState=18) and (Character='A') then
begin
GettingBarcode:=True;
CurrentBarcode:='';
Handled:=true;
end;
end;
end;

Categories