Jump to content

Add a character to keyboard/barcode scanner input?


Recommended Posts

I have a barcode scanner and in the program I'm using it I have to press B before the barcode reader data can be input.

Barcode reader is working as a keyboard basically through USB and uses the HID drivers:

hidclass.sys

hidparse.sys

hidusb.sys

hid.dll

I wonder if it's possible to intercept the data and add that B with some clever AutoIt script so I don't have to press it every time. I thought I'd explore this option before I start working on a hardware solution. Currently I'm only using AutoIt to close a few programs if I loose connection to one of my service providers and restart them when I get the connection back - works very well, didn't write it myself though.

What I get from the barcode scanner now:

/1//XXXX/1/1/1%

What I'd like to get:

B/1//XXXX/1/1/1%

Link to comment
Share on other sites

Func _esc()
Exit MsgBox(262144, " ", "End of barcode interception", 3)
EndFunc ;==>_esc

Func _percent()
HotKeySet("%")
Send("%")
HotKeySet("/", "_slash")
EndFunc ;==>_percent

Func _slash()
HotKeySet("/")
Send("B/")
HotKeySet("%", "_percent")
EndFunc ;==>_slash

HotKeySet("{ESC}", "_esc")
HotKeySet("/", "_slash")
MsgBox(262144, " ", "Press ESC to stop barcode interception", 3)

While 1
Sleep(9999999)
WEnd

App: Au3toCmd              UDF: _SingleScript()                             

Link to comment
Share on other sites

Tried it, almost worked.

I probably should have a few 100 ms delay after the B and then send the rest, as it opens up a new window.

(Scanning a bar code with B/1//CBJN/1/2/1% works very well though, so something seems fishy here.)

Anyway, there's mixed results, I scanned this code: /1//CBJN/1/2/1%

Didn't manage to get it right a single time in the program, here's a list of consecutive scans, seems it shifts characters sometimes as well:

B!///CBJN/1/2/1% (shifted 1, 1 and / changed places)

B1///CBJN/1/2/1 (1 and / changed places, % and enter changed places)

%b1///CBJN/1/2/1% (1 and / changed places)

B!///CBJN/1/2/15 (1 and / changed places, 1 and % are shifted)

b1///CBJN/1/2/1% (etc)

B!///CBJN/1/2/1%

!B///CBJN/1/2/15

b1///CBJN/1/2/1

%B1///CBJN/1/2/15

b1///CBJN/1/2/1

%b1///CBJN/1/2/1%

!B///CBJN/1/2/15

!B///CBJN/1/2/15

b1///CBJN/1/2/1

%b1///CBJN/1/2/1

%b1///CBJN/1/2/1

%b1///CBJN/1/2/1%

b1///CBJN/1/2/1%

B!///CBJN/1/2/15

B1///CBJN/1/2/1%

B1///CBJN/1/2/1%

B!///CBJN/1/2/1%

B1///CBJN/1/2/1%

B1///CBJN/1/2/1

%!B///CBJN/1/2/15

B1///CBJN/1/2/15

b1///CBJN/1/2/1%

b1///CBJN/1/2/1%

!B///CBJN/1/2/15

b1///CBJN/1/2/1%

b1///CBJN/1/2/1%

!B///CBJN/1/2/15

b1///CBJN/1/2/1%

Whenever the b or B (doesn't matter really) comes first (as it is supposed to) the / and 1 seems to trade places.

Link to comment
Share on other sites

Or try this

Func _esc()
Exit MsgBox(262144, " ", "End of barcode interception", 2)
EndFunc ;==>_esc

Func _enter()
HotKeySet("{enter}")
Send("{enter}B")
HotKeySet("{enter}", "_enter")
EndFunc ;==>_enter

Opt("SendKeyDelay", 0)
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")
Send("B")
MsgBox(262144, " ", "Press ESC to stop barcode interception", 2)

While 1
Sleep(9999999)
WEnd

App: Au3toCmd              UDF: _SingleScript()                             

Link to comment
Share on other sites

Second version is a no-go, it adds the text normally and then a B after enter, doesn't seem to mess up the order though.

/1//CBJN/1/2/1%

B/1//CBJN/1/2/1%

B/1//CBJN/1/2/1%

B

etc

Can't have the "reading barcode" window up and waiting directly after reading a barcode.

Seems it messes with the caps lock function as well, got lower case characters on the four letters suddenly.

Just adding the Opt("... line ended up having this result:

B/!//CBJN/1/2/1%

B/!//CBJN/1/2/1%

B!///CBJN/1/2/1%

B71//CBJN/1/2/1%

B/!//CBJN/1/2/1%

B71//CBJN/1/2/1%

B/!//CBJN/1/2/1%

B/!//CBJN/1/2/1%

B/!//CBJN/1/2/1%

B!///CBJN/1/2/1%

B/!//CBJN/1/2/1%

B!///CBJN/1/2/1%

B/!//CBJN/1/2/1%

B/!//CBJN/1/2/1%

A combination of these two might work, first one looked really good but I guess it's trickier adding a letter in front instead of one after.

Perhaps it should trig on the / and then send an erase for each character (and save it) until enter trigs sending the entire code with a B first. Or trig on /, count the characters until a trig on enter erases the same amount and enters them again but with a B first.

Unless something more elegant can be thought up...

Feels like it's close.

Edited by e5frog
Link to comment
Share on other sites

Perhaps a sleep before and after "B" ?

Func _esc()
Exit MsgBox(262144, " ", "End of barcode interception", 2)
EndFunc ;==>_esc

Func _enter()
HotKeySet("{enter}")
Send("{enter}")
HotKeySet("{enter}", "_enter")
Sleep(1000) ; wait a second
Send("B") ;
Sleep(1000) ; wait a second
EndFunc ;==>_enter

Opt("SendKeyDelay", 0)
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")
Send("B")
MsgBox(262144, " ", "Press ESC to stop barcode interception", 2)

While 1
Sleep(9999999)
WEnd

App: Au3toCmd              UDF: _SingleScript()                             

Link to comment
Share on other sites

The way I work is that I scan a barcode then click around with the mouse in the program for maybe 5-20 minutes before the earliest scan of the next code... so that doesn't seem like a good idea.

It works but the window that is popped up by pressing B would be out of focus when the barcode is read after finish working in the program and going on to the next barcode.

It would be just perfect if the trigger button on the scanner could be sensed but that doesn't seem to be possible, I could let the trigger write a B and then read the barcode...

Some kind of buffer would be handy as the scanner seems to be too fast for the script, but is it possible to prevent or redirect the input from one device somehow?

EDIT:

If this code could be used globally in Windows I could perhaps prevent any code from being entered from the barcode scanner:

http://www.autoitscript.com/wiki/Snippets_%28_AutoIt_Mouse_%26_Keyboard_%29#Restricted_Input_Keys_-_All_USB_Devices_.7E_Author_-_Multiple_Authors

Save the data, send a B and then the caught data, if it has the same handy ESC-key shutdown it will be easy to shut it off if I need to write anything - for example here in the forum. ;-)

EDIT2:

Or handle the dll files directly like this one does:

http://www.autoitscript.com/wiki/Snippets_%28_AutoIt_Mouse_%26_Keyboard_%29#WinAPI_SwapMouseButton.28.29_.7E_Author_-_guinness

Edited by e5frog
Link to comment
Share on other sites

I tried a key logger that I found on stackoverflow.com to see if I could save the keystrokes from the scanner in a file - nope, all mixed up.

/1//BUKR/1/3/1%

/1//XKJO/1/2/1%

/1//EHTA/1/1/1%

Were saved as:

{SHIFT}17bkru{ENTER}{SHIFT}13577x{SHIFT}1257jko{ENTER}{SHIFT}17aeht{ENTER}{SHIFT}157{RIGHT MOUSE}

Not that handy.

Are there a keystroke speed checker anywhere so I can check how fast it writes the characters?

Link to comment
Share on other sites

Is reading the output after it's scanned in and reformatting it in the field an option?

I can see it being easier to just let the scanner read the information, wait for it to populate, then alter the output field.

EDIT: Better idea... make a small script that is a substitute for the app you're using to scan your barcodes. Replace the shortcut for your app with the script, run the app, and looping looking for the window of the input screen. If the input screen comes up, popup a InputBox to accept the scanned information, work your magic on the string, then output it to the app.

Edited by mechaflash213
Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Link to comment
Share on other sites

The reason for this is to not having to press B on the keyboard to open up the input window that can receive the code from the barcode reader. The input window doesn't appear until B is pressed...

It's perhaps possible if another window, opened by a script could take the whole input, then change focus to the program I'm using, send a B and then the code that was scanned. But after that I'd be in my program working for a while, then I'd have to remember to change focus to the scripted window again - which I can do with the mouse though... Seems possible but a semi-solution as it adds a new step to it.

I'm not 100% sure I understand what you mean mechaflash213, if you have a link or an example I can perhaps play around with it.

When trying the keylogger program It was possible to lower the sleep time but even with no "sleep" at all the input wasn't the way it should, things were repeated four OR five times and things wasn't logged in the order they were supposed to. Logging data to a file is perhaps not a very quick and handy way. Not sure if the correct data could be filtered out of that but as there's a narrow window of possible combinations and an even narrower window of usually used combinations - maybe it would, it would require a lot more complicated solution than I had hoped for after seeing the initial code suggestion - that almost worked.

Edited by e5frog
Link to comment
Share on other sites

I just thought of something...

As long as there's no B in the barcoded characters it wouldn't really happen anything if I scan a barcode with the program up and running. If I could just save the whole thing in a buffer I could just re-send it with a B in front of it...

How do I block B:s though and how do I temporarily store the data?

I tried making a barcode with just a B but that didn't help as the barcode reader adds a return after it, it would only be a partial solution to this "problem" as well if it can be removed... I'd have to scan two codes.

Edited by e5frog
Link to comment
Share on other sites

try this:

Opt("SendKeyDelay", 0)
Global $buffer = ""
For $i = 20 To 255
HotKeySet(Chr($i), "_HotKeys")
Next
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")
MsgBox(262144, " ", "Press ESC to stop barcode interception", 2)
While 1
Sleep(9999999)
WEnd
Exit

Func _HotKeys()
;Beep(1000, 50) ; listen during testing
$buffer &= @HotKeyPressed
EndFunc ;==>_HotKeys

Func _esc()
Exit MsgBox(262144, " ", "End of barcode interception", 2)
EndFunc ;==>_esc

Func _enter()
For $i = 20 To 255
HotKeySet(Chr($i))
Next
HotKeySet("{enter}")
;MsgBox(262144, " ", "" & $buffer, 0)
Send("B") ;
Sleep(500) ; wait for barcode popup (or do a winwaitactive)
Send($buffer, 1)
$buffer = ""
Send("{enter}")
For $i = 20 To 255
HotKeySet(Chr($i), "_HotKeys")
Next
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")
EndFunc ;==>_enter

App: Au3toCmd              UDF: _SingleScript()                             

Link to comment
Share on other sites

If I am interpreting this correctly it appears as though the script is sending keys while the barcode scanner input window is still open. If there is a window, or other process, that must be opened via the B key for input then avoid hotkeys altogether and have a loop pressing the B key. Then us WinWaitNotActive() or ProcessExists() to pause the script while the scanner input window is open to avoid interference with the scan.

Link to comment
Share on other sites

Streamlined the code and added an audiable alarm.

Opt("SendKeyDelay", 0)
Global $buffer = ""
For $i = 20 To 255
HotKeySet(Chr($i), "_HotKeys")
Next
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")
MsgBox(262144, " ", "Press ESC to stop barcode interception", 2)
While Sleep(20000)
Beep(2000, 50) ; beep every 20 seconds to indicate active barcode interception
WEnd
Exit

Func _HotKeys()
$buffer &= @HotKeyPressed
EndFunc ;==>_HotKeys

Func _esc()
Exit MsgBox(262144, " ", "End of barcode interception", 2)
EndFunc ;==>_esc

Func _enter()
HotKeySet("B")
Send("B")
HotKeySet("B", "_HotKeys")
Sleep(500) ; wait for barcode popup (or do a winwaitactive)
For $i = 1 To StringLen($buffer)
$c = StringMid($buffer, $i, 1)
HotKeySet($c)
Send($c, 1)
HotKeySet($c, "_HotKeys")
Next
HotKeySet("{enter}")
Send("{enter}")
HotKeySet("{enter}", "_enter")
HotKeySet("{ESC}", "_esc")
$buffer = ""
EndFunc ;==>_enter

App: Au3toCmd              UDF: _SingleScript()                             

Link to comment
Share on other sites

  • 2 months later...

Tried that last piece of code and it seems to work great with the scanner now!!

New problem though is I can't use the keyboard when the script is active. :-(

For example if I want to log in here. ;-)

Perhaps the HotKey "Esc" could disable the scanner helper until it was pressed again - or other button?

Just press Esc to be able to use the keyboard and then Esc again to re-activate the blockage. Don't understand what part of the code is blocking input...

I searched for this again today (before I googled my way here again) and found a very similar problem here:

http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/

Seems he was able to differentiate the plain USB keyboard from the USB scanner.

Would be really really really handy if it was possible to auto focus the program upon a scanner read, can that be done easily and how do I identify the program?

So just two more things to solve, keyboard working either automatically or by pressing certain key and getting focus automatically on the window.

Great work!

BTW: Does anyone know if you can choose your own tray icon instead of the AutoIt?

Edited by e5frog
Link to comment
Share on other sites

I added two lines to the code so now I don't have to activate the window manually, I can just scan the barcode at any time:

Func _enter()
WinActivate("[CLASS:AftMainWindowClass]", "")
WinWaitActive("[CLASS:AftMainWindowClass]")
HotKeySet("B")
Send("B")
... etc

Only one thing left - leave the real keyboard out of it if possible or add a simple on/off function, I guess instead of EndFunc on the _esc there could be a check for a new Esc press to get back to the program somehow - as a temporary solution at least.

I changed the _HotKeys so it only uses the ones that may appear, that gives some freedome to type.

Opt("SendKeyDelay", 0)
Global $buffer = ""
For $i = 65 To 90 ;uppercase characters
HotKeySet(Chr($i), "_HotKeys")
Next
HotKeySet(Chr(37), "_HotKeys") ; % sign
HotKeySet(Chr(47), "_HotKeys") ; / sign
For $j = 48 To 57 ; numbers
HotKeySet(Chr($j), "_HotKeys")
Next
HotKeySet("{ESC}", "_esc")
HotKeySet("{enter}", "_enter")

Which meant I could also type until Enter is pressed... ;-)

So still need a workaround to be able to use the keyboard when needed.

Edited by e5frog
Link to comment
Share on other sites

Here's the current code, I start the program if it's not active (thought I should replace the existing Icons with this program).

Added on/off function with only Esc as special key when off, removed Enter as hotkey so I can still write lowercase letters when the scanner helper is active, as all codes end with % that was not a problem.

Works pretty well, would be perfect if it could see the difference between the "two keyboards" (as one is a scanner).

Left to do in this version is checking if it's a valid code being read and only send then. When I played around I suddenly got a bunch of {enter} in the barcode input box... that would be better if it couldn't happen. Error message and clear buffer. A valid code would be something with at least six / characters, ending with a % and contain nothing more than numbers, capital letters and these two characters. Program complains if the code is invalid of course, it hasn't happen more than once when I intentionally didn't scan in a proper way.

If WinExists("[CLASS:AftMainWindowClass]") = 0 Then
Run("C:\Rep2000\rep2000.exe")
Endif

Opt("SendKeyDelay", 0)
Global $buffer = ""
_start()
While Sleep(20000)
;Beep(1000, 50) ; beep every 10 seconds to indicate active barcode interception
WEnd
Exit

Func _HotKeys()
$buffer &= @HotKeyPressed
EndFunc ;==>_HotKeys

Func _esc()
HotKeySet("{ESC}", "_start")
; remove HotKey function for normal operation except for Esc
For $i = 65 To 90 ;uppercase characters
HotKeySet(Chr($i))
Next
HotKeySet(Chr(37)) ; % sign
HotKeySet(Chr(47)) ; / sign
For $j = 48 To 57 ; numbers
HotKeySet(Chr($j))
Next
MsgBox(64, "Fredric's scanner-helper", "Scanner-helper inactive." & @CRLF & "Activate with Esc", 10)
While 1=1
Sleep(500)
Wend
EndFunc ;==>_esc

Func _start()
For $i = 65 To 90 ;uppercase characters
HotKeySet(Chr($i), "_HotKeys")
Next
HotKeySet(Chr(37), "_enter") ; % sign
HotKeySet(Chr(47), "_HotKeys") ; / sign
For $j = 48 To 57 ; numbers
HotKeySet(Chr($j), "_HotKeys")
Next
HotKeySet("{ESC}", "_esc")
$buffer = ""
MsgBox(64, "Fredric's scanner-helper", "Scanner-helper inactive." & @CRLF & "Deactivate with Esc", 10)
EndFunc ;==>_restart

Func _enter()

; TODO
; valid code check?
; Start with / end with %

; At invalid code, exit this Function and MsgBox

WinActivate("[CLASS:AftMainWindowClass]", "")
WinWaitActive("[CLASS:AftMainWindowClass]")
WinSetState ( "[CLASS:AftMainWindowClass]", "", @SW_MAXIMIZE )
HotKeySet("B") ; remove HotKey assignment
Send("B") ; Send a B
HotKeySet("B", "_HotKeys") ; Re-assign B as HotKey
WinWaitActive("Read bar-code") ; Wait for the barcode window Title: "Read bar-code"
For $i = 1 To StringLen($buffer) ; Send the recorded code
$c = StringMid($buffer, $i, 1)
HotKeySet($c)
Send($c, 1)
HotKeySet($c, "_HotKeys")
Next
HotKeySet("%")
Send("%")
Send("{enter}")
HotKeySet(Chr(37), "_enter") ; % sign
HotKeySet("{ESC}", "_esc")
$buffer = ""
EndFunc ;==>_enter
Link to comment
Share on other sites

I used the upx in the AutoIt package to unpack the .exe so I could replace the icon with Resource Hacker as well, came out pretty nice.

Have also fine tuned it a little more to handle a few errors and such as well I think it will work nicely.

Thank you very very very very much for all the help.

New possibilities open to help here and there with most stuff.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...