Sendkeys to DOS application

G

Guest

Hi there,

I need to develop a program that captures input from a serial port and/or
network and fools a native DOS application into thinking it comes from the
keyboard.
I've tried using Windows.Forms.Sendkeys.Send(), but I encountered an
exception every time the method was called (something about the application
not listening for Windows messages).
I changed the code to use Windows.Forms.Sendkeys.SendWait(), and that works
fine for windows apps (tested in Notepad, Word, ...) and works even for the
command prompt (cmd.exe) in winXP. But DOS applications don't seem to get the
right keystrokes.
When I tried to use it on EDIT.EXE, nothing showed up. When I tried it on
the appliccation I'm actually willing to use it on, I got unexplained
results: the program returns to the main screen when the sendkeys is
performed, showing that it does receive a message of some kind (otherwise, it
wouldn't return to the main menu screen), but not the right data (which is a
command string, followed by {ENTER}), because then the program should execute
the command.

I've been searching the Knowledge Base and the Internet, but found only
relevant info for VB3 and VB4, being pre-in the WindowsXP days.

The program should be capable to perform it's 'duty' in a variety of locales
and with a variety of keyboard layouts, and it should work on upcomming
Windows releases, as wel as previous versions (from Win95 on).

Anybody got a solution to my problem??
 
G

Guest

Hi,

Thanks for your quick reply. I've wrote the code using the SendInput
function, but this yields the same results as the SendKeys method: Works fine
for Windows, doesn't work for DOS.
Any other suggestions??
Thanks in advance!!
 
L

Lau Lei Cheong

Perheps... you could just send the key to CMD.exe your console application
is running?

Console applications do not have message loop so won't response to SendKey()
or other kind of method make use of Windows system message.

Anyway, for serial ports why don't just use pipe redirection like
"yourapp.exe < com1"?
 
G

Gabriele G. Ponti

Make sure that the window hosting the DOS session is active, and that you
send one character at the time with a little delay between each character
(10 milliseconds should do it).

If this doesn't help try posting the code you wrote and somebody may be able
to help you.

Gabriele
 
G

Guest

Hi,

How would I send the keystrokes to the CMD.exe? Neither sendkeys, nor
sendinput allow to specify the process that should receive the keystrokes.

I can't use redirection because:
1. The program still needs to respond to keyboard input
2. The automated input would not only be coming from the serial port, but
also network (and maybe other sources in the future)
3. Some command need to be processed (changed) before they reach the
application.
 
G

Guest

Hi there,

The window with the DOS session is active indeed. I tried both fullscreen
and in a window, neither works.

for the code (VB), my first attempt was this (extract):

Dim sb As New System.Text.StringBuilder(data)
sb.Replace(ControlChars.Back, "{BACKSPACE}")
sb.Replace(ControlChars.CrLf, "{ENTER}")
sb.Replace(ControlChars.Cr, "{ENTER}")
sb.Replace(ControlChars.Lf, "{ENTER}")
sb.Replace(ControlChars.Tab, "{TAB}")

Windows.Forms.SendKeys.SendWait(sb.ToString)
Windows.Forms.SendKeys.Flush()

I tried inserting DoEvents() calls here and there, but didn't work.

Then, after your first reply, i wrote the following wrapper for the
SendInput API function:

Public Function SendKeys(ByVal data As String) As Integer
data = data.ToUpper
Dim ASCIIdata As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
Dim KeyStrokes(ASCIIdata.Length - 1) As INPUT
For character As Integer = 0 To ASCIIdata.Length - 1
Select Case ASCIIdata(character)
Case CByte(48) To CByte(57)
ASCIIdata(character) += CByte(48)
End Select
KeyStrokes(character).type = INPUT_KEYBOARD
With KeyStrokes(character).ki
.wScan = 0
.dwFlags = 0
.time = 0
.wVk = CShort(ASCIIdata(character))
.dwExtraInfo = GetMessageExtraInfo()
End With
Next character
SendInput(KeyStrokes.Length, KeyStrokes(0),
System.Runtime.InteropServices.Marshal.SizeOf(KeyStrokes(0)))
End Function

And called that function with the data: similar results...

Just now, after your last reply, I tried (just as a test) to send one
keystroke at a time (with both SendKeys and the SendInput wrapper), separated
by Thread.Sleep(100)... Same results...
 
G

Gabriele G. Ponti

The way you're using the SendInput is not correct. Because you're
synthesizing keystrokes you have to reproduce all the steps necessary to
send a single character.

For example to send the "A" you would have to do a shift down, "a" down,
"a" up, shift up.

The C# example on the pinvoke.net site
(http://www.pinvoke.net/default.aspx/user32/SendInput.html) shows the
correct way to use SendInput.

Gabriele
 
J

Jelle Mous

I know that's what it's supposed to be. But at the moment I was just testing
and didn't care yet about character casing.

Gr,

JM
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top