How do I use WScript.Shell SendKeys to send Number Pad key strokes? - vbscript

I am trying to use WScript.Shell SendKeys method to emulate sending a key press from the Number Pad.
I have an application that I am writing automated testing for using QTP. It is a Web Browser based application and the input is into a Java App within the web page. The input only accepts key presses from the Number Pad and the Enter key.
So far I am using this code:
Dim strInputKey
strInputKey = "{ENTER}"
Set objWsh = CreateObject("WScript.Shell")
Browser("Launch Browser").Page("Test Application").WebElement("Item ID").Click
objWsh.SendKeys strInputKey
This works fine for sending the Enter key, but I can't quite figure out if there is a way to send Number Keys. Any help would be greatly appreciated.
I am not sure if there are any undocumented ways of achieving this. I have read http://msdn.microsoft.com/en-us/library/8c6yea83(VS.85).aspx but it doesn't go into great detail.

I don't have the rep to comment on the above answer that said
objWsh.SendKeys chr(79) & chr(80) & chr(81)
but I don't think it's correct
objWsh.SendKeys chr(79) & chr(80) & chr(81)
For a start, it sends the letters O,P,Q
And he wants numbers, like 1234567890
and the link goes to keyboard scan codes.. I think those are for knowing what key on the keyboard was pressed. They are different from ascii codes.
79,80,81 are the keyboard scan codes for some numbers on the number pad / numpad.
Chr though, uses ascii codes. not keyboard scan codes.
Furthermore, just specifying a digit, here, since it isn't done by pressing a key, it doesn't specify and needn't specify, which was key was used, since a key wasn't used.
To sendkeys some numbers (from the number pad), is just same as sending keys from the top row. You just want to send some numbers.
If all he wants to know is how to use sendkeys to send digits, then obviously.
objWsh.SendKeys 12345
or
str="12345"
objWsh.SendKeys str
But if the questioner didn't realise that objWsh.SendKeys 12345 would do it, then perhaps the questioner is just confused. I guess from the green tick, he voted an answer that is like objWsh.SendKeys "OPQ".
I am aware that this is an old question, but for the sake of haing correct questions and answers..

You'll need to use the keycodes for the number pad.
Here's a list of them:
http://www.empirisoft.com/directrt/help/_helpcontents.htm?directrt_key_codes.htm
So to send "123", you would need to do:
objWsh.SendKeys chr(79) & chr(80) & chr(81)

Related

Interpret "Find action" results on Safari

I am trying to create an AppleScript that can find text on a webpage and tell me the amount of matches I received(Command + F).
I already know how to do the "Find" part:
tell application "System Events"
delay 0.5
keystroke "f" using {command down}
end tell
However, I do not know how to interpret these results, such as tell me whether there is a match, or how many matches I have.
Is there any way to do this?(If it seems a bit vague, I can be more specific)
Thanks!
I agree with #user3439894 and his sentiments about using UI scripting (that is—in this case—getting System Events to issue mouse clicks and keypresses on your behalf). Although it has its uses in other areas, it's by far and away my personal least favourite method to achieve a goal, and one of last resort.
Two very quick reasons why it can be a fragile implementation is: 1) the CmdF shortcut used to initiate the Find... menu command could change, either by your own doing, or if it were to be overridden by a systemwide shortcut that supersedes Safari's claim to it (in fact, for this reason, I would personally trigger the Find... command via the menu bar, which System Events can click on your behalf. Menu items tend not to change like shortcuts, unless regional language settings do); and 2) if Safari loses focus during the time the keypresses are issued and the search is initiated, it messes up the whole command flow in your script, and will at best give you no results, but more likely, throw an error in a later part of the script.
I'm going to demonstrate two alternative methods of searching a Safari webpage for a piece of text, and obtaining the number of times it matches throughout the whole document.
1. Safari's do JavaScript AppleScript command
Most modern web browsers have the ability to run JavaScript code inside their tabs, and Safari can too. AppleScript can take command of this very useful function, provided you give it permission to do so by going into the Develop menu of Safari and ticking Allow JavaScript from Apple Events and Allow Remote Automation (the latter of which will already be on, I'm guessing). There's another menu item called Allow JavaScript from Smart Search Field—I would advise you keep this one off, otherwise it could potentially allow naughty websites to issue commands to your computer and cause mischief.
use A : application "Safari"
set D to the front document of A
set s to "AppleScript" -- the search string
try
set n to (do JavaScript ¬
"document" & ¬
".body" & ¬
".innerText" & ¬
".match(/" & s & "/ig)" & ¬
".length;" in D) as integer -- the number of matches
on error
set n to 0
end try
To break this down: s is the search string that you would otherwise be typing into the search box. It is fed into a JavaScript command, that has the following components:
document: a reference to the Safari webpage document;
body: the body of the document, as opposed to, say, the header or the footer. It's the main bulk of the webpage that users see in front of them;
innerText: the text contained within the body of the document, free of any HTML formatting, but preserving whitespace;
match(): a method or function in JavaScript where the search string s is used to perform a search within the innerText and return an array listing all of the matches;
length: a property of the array returned by match() that reports how many elements is contains, and this equates to the number of matches found during the search.
It's all one command, which, written in full on a single line, looks like this (using the search string "AppleScript"):
document.body.innerText.match(/AppleScript/ig).length;
It returns a number, which is stored in the variable n, and that's it.
This is my favourite method that I would elect to use myself, as it's unlikely to break, and it's nice and fast.
I should point out that match() actually searches and matches using a Regular Expression. I won't go into them right now, but it means that the search string s will need to be a little careful if using any special characters:
\ [ ] { } ^ $ . | ? * + ( )
All you need to be aware of is that, if your search string uses any of these characters, you should precede it with a double-backslash \\. So, for example, if I wanted to search for "matches I received(Command + F)" (which uses (, ) and +), then I would declare my variable s as:
set s to "matches I received\\(Command \\+ F\\)"
2. Chop & Measure
This method is useful if you don't wish to enable Remote JavaScript in your browser, or simply want something that's straightforward to remember and implement off the top of your head next time.
It's simple text manipulation, using AppleScript's text item delimiters and a bit of counting:
use A : application "Safari"
set D to the front document of A
set s to "AppleScript" -- the search string
set T to text of D -- the webpage text content
set l to {initialValue:length of T, finalValue:missing value}
set the text item delimiters to s
set T to text items of T
set the text item delimiters to ""
set T to T as text
set l's finalValue to length of T
set |𝚫l| to (l's initialValue) - (l's finalValue)
set n to |𝚫l| / (length of s)
Safari has a useful AppleScript property called text, which refers to the text content of the specified document or tab (it also has another property called source that contains the HTML source of the document or tab).
Here's the breakdown:
The value of Safari's text property—which is the text content of the webpage—is stored in a variable, T;
The length of T is read and stored. This equates to the number of characters on the whole webpage;
The text item delimiters are set to the search string, s, (which does not need to worry about special characters, so don't insert unnecessary backslashes in this one). The text item delimiters basically erase all occurrences of s from within T;
Then the length of T is read again. If s found any matches in T, it means that the length of T—the number of characters—will have reduced;
It will have reduced by the number of characters in s for each match that occurred. Therefore, turning the equation round a bit, the number of matches, n, is equal to the change in length of T divided by the length of s.
There are other ways to search a webpage with AppleScript, JavaScript, bash, etc., but I think these two serve as reasonable examples of how to achieve the same goal using very different methods. I refer to them as examples, because you might need to make small adjustments to the script to cater for your own needs, such as inserting backslashes where necessary in the first example, or considering in the second how you'd handle the situation if you set s to be an empty string "" (it will throw an error, but this is easily managed).
They also both return real values for n, i.e. 11.0. It's easy to see why in the second example, but I assume it's just a type conversion between JavaScript and AppleScript in the first example (I don't know). Therefore, purely for neatness, I would then coerce the returned value into an integer as I did in the first one, so it reads 11 instead of 11.0:
set n to (...) as integer
but you don't have to.
First of all I must say that UI Scripting can be messy and unreliable. I'd suggest you find a different way to accomplish whatever the real goal is.
That said, using Safari in macOS High Sierra 10.13.3 set to this web page, the following example AppleScript code will set the variable theSearchResult to the result of the search for the word "vague":
tell application "Safari" to activate
delay 0.5
tell application "System Events"
keystroke "f" using command down
delay 0.2
keystroke "vague"
delay 0.2
set theSearchResult to (value of static text 1 of group 2 of tab group 1 of splitter group 1 of window 1 of application process "Safari")
delay 0.2
key code 53 -- # Esc
end tell
return theSearchResult
Result:
"1 match"
Note that the value of the delay commands may need to be adjusted for your system, and or additional delay commands may or may not be needed. Adjust values of and or add/remove the delay commands as appropriate.
The search result can be one of the following, Not found or an integer followed by the word match, e.g. 1 match, and possibly something else, not sure as I've not done extensive testing.
How you want to interpret the result is up to you. You could use a if statement on the theSearchResult, e.g.:
if theSearchResult contains "Not found" then
-- # Do something.
-- # Your code goes here.
else
-- # Do something else.
-- # Your code goes here
end if
Another factor to consider is how is it being searched, i.e. Starts With or Contains. I believe the default in for Safari in macOS High Sierra 10.13.3 is Starts With.
Note: The example AppleScript code is just that and does not employ any error handling and is meant only to show one of many ways to accomplish a task. The onus is always upon the User to add/use appropriate error handling as needed/wanted.

Injecting key combinations into Bash tty using TIOCSTI in Python

I am trying to inject key combinations (like ALT+.) into a tty using the TIOCSTI in Python.
For some key combinations I have found the corresponding hex code for Bash shells using the following table which works good.
From this table I can see that for example CTRL+A is '\x01' etc.
import sys,os,Queue
import termios,fcntl
# replace xx with a tty num
tty_name = "/dev/pts/xx";
parent_fd = os.open(tty_name, os.O_RDWR)
special_char = "Ctrl_a"
if special_char == "Ctrl_a":
send_char = '\x01'
if special_char == "Ctrl_e":
send_char = '\x05'
if special_char == "Ctrl_c":
send_char = '\x03'
fcntl.ioctl(self.parent_fd, termios.TIOCSTI, send_char)
But how can I get the hex codes for other combinations such as
ALT+f etc. I need a full list or a way how to get this information for any possible combo as I want to implement most bash shortcuts for moving, manipulating the history etc. to inject.
Or is there any other way to inject key-combinations using TIOCSTI ?
As I can only send single chars to a tty I wonder if there is anything else possible.
Thank you very much for your help!
The usual working of "control codes" is that the "control" modifier substracts 64 from the character code.
"A" is ASCII character 65, so "Ctrl-A" is "65-64=1".
Is it enough for you to extend this scheme to your situation?
So, if you need the control code for, for example, "Device Control 4" (ASCII code 20), you'd add 64, to obtain "84", which is "T".
Therefore, the control-code for DC4 would be "Control+T".
In the reverse direction, the value for "Control+R" (history search in BASH) is R-64, so 82-64=18 (Device Control 2)
ASCIItable.com can help with a complete listing of all character codes in ASCII
Update: Since you were asking specifically for "alt+.":
The 'Control mean minus 64" doesn't apply to Alt, unfortunately; that seems to be handled completely differently, by the keyboard driver, by generating "key codes" (also called "scancodes", variably written with or without spaces) that don't necessarily map to ASCII. (Keycodes just happen to map to ASCII for 0-9 and A-Z, which leads to much confusion)
This page lists some more keycodes, including "155" for "alt+."

Determine if Control key was used to generate character in WM_CHAR

When receiving character input, is there a way to know whether the character code in wParam was generated as a result of the keyboard state we get back from GetKeyboardState()? For example, if you hit Ctrl+A then the character 'a' would not be a result of the control key but if you're using a Swedish keyboard and type Ctrl+Alt+7 the result would be {. In that case, is there any way of knowing that the keyboard state (Ctrl and Alt) were necessary to generate that character code?
(To be honest, as an English speaker who has really only ever used a US keyboard layout, I have no definite idea that this will work, but...) I believe that the VkKeyScan function (or VkKeyScanEx) might do what you want.
As input, it takes a character, not a scan code or a virtual key, so this is the wParam value that you get from WM_CHAR.
Its return is a value that provides both the virtual-key code (which I guess you can ignore) in the low-byte, and the (mis-named) "shift state" in the high-byte, which is actually a set of flags representing the qualifier keys needed to produce that character.
So if you get a WM_CHAR message and wanted to tell if the control key was needed in order to generate it, in theory you could do:
case WM_CHAR:
if (HIBYTE(VkKeyScan((TCHAR)wParam)) & 2) {
// control pressed!
}
break;
If you are only looking at the data provided by the WM_CHAR message, then no. You would likely have to look at the WM_KEY... messages to keep track of what the surrounding keystrokes where doing at the time, if Get(Async)KeyboardState() does not provide what you need.

Letters in DTMF | GRXML | Multiple Keypress on same number

Hi i need to know whether we can use letters(alphabets) in dtmf or touchtone in ivr application(genesys).if possible how can we use it?
FYI.,
i came to know after reading several forums,i can use the code which is given below.i need to know whether it is correct.if wrong let me know the grammar code
I need the scenario like if press '2' one time,i need 'a' and if press '2' two times i need 'b',etc..,
[(dtmf-2)] = 'a'
[(dtmf-2 dtmf-2)] = 'b'
[(dtmf-2 dtmf-2 dtmf-2)] = 'c'
In the following link,we have ABCD separate.whether it is available in all phones?
http://nemesis.lonestar.org/reference/telecom/signaling/dtmf.html
This is an old technique for spelling things out to an IVR application using DTMF. All phones use DTMF to transmit what keys are pressed. It will work on any IVR but it is up to the application developer of the IVR application to translate what the digits mean, and you need to give the user some direction on how to do this in the voice prompts. It is a very error prone method and it is best to give the user feedback on what you think they are trying to enter. But this is all we had before speech recognition came along.
Basically this is just using the letters on telephone keys as the guide. The letters "A", "B" and "C" are on key "2". You are telling them to press "2" the number of times that the letter appears in sequence on the key (i.e. "A" is first, "B" is second, and "C" is third). This method works fine for getting a single letter but it does not work so well for multiple letters unless you have the user pause for certain length of time to indicate they are finished. The IVR takes the length of silence as the ending of inputting a letter.
Another technique is to use two key presses for each letter, again using the sequence the letters appear on the number key as the guide. So the letter "A" would be 21, "B" is 22, "C" is 23, "D" is 31, etc... This technique does not require long pauses between entering a letter because the IVR knows there will be two key presses for each letter.

RS232c VB6 help

Hey all, i am trying to turn on a A/V Reciever with a RS232 command using the VB6 comm32. To turn it on it says to use:
Command code Parameter code CR Code set example
PW ON <CR> PWON<CR>
And this is my VB6 code i am currently using that doesnt seem to work...
MSComm.CommPort = 2
MSComm.Settings = "9600,n,8,1"
MSComm.PortOpen = True
If Not MSComm.PortOpen Then
MsgBox "not opened"
Else
MSComm.Output = "PWON" & Chr(13)
Do While MSComm.InBufferCount > 0
Text1.Text = Text1.Text & MSComm.Input
Loop
End If
The reciever never turns on. What could i be doing incorrectly? I checked to make sure the com port was 2 and it is.
David
You are just sending the characters <CR> rather than a real carriage return (ASCII code 13). Documentation for serial peripherals often puts the names of control characters in brackets (see Wikipedia for a list of them). You need the line:
MSComm.Output = "PWON" & Chr(13)
It also seems that the code that follows to read data from the serial port should be changed because if the data has not arrived in the serial port's buffer yet, it will read nothing. Take a look at Microsoft's example for how to do so. You could decide to stop reading once a particular substring in the input has been found, once a certain number of bytes have been read (Len function), etc.

Resources