Sending hot keys to applications

Nov 2, 2012 at 4:57 PM

Hello, it's me (again).

I'm trying to use Invoke-UIAHotKey cmdlet, but since this does not accept pipeline input, I don't see a way to invoke a hot key onto another application.

I also tried playing with Set-UIAControlKeys (Get-UIAWindow ... | Set-UIAControlKeys ...) but does not work as expected. I see the desired control highlighted, but then the hot key does not pass through. If I set a simple text (like 'test') and run in powershell console, the command returns True, and the text is output in the console.

Is there a way to do this?

Nov 2, 2012 at 8:44 PM

Hello again,

if you need to send a hotkey (an accelerator key or access key), I can't offer much.

First of all, an accelerator key is a well-known short cut like Ctrl+C and access key is an Alt+{character} combination.

You need to work with accelerator keys, don't you?

Now, what we have:

1) Invoke-UIAHotkey is a wrapper over the keyb_event API call. This call does not use handles, in other words, it sends keys to any receiver. 

I'd only suggest to use something like:

Get-UIA[ControlType]; Invoke-UIAHotkey "..." 
# or 
Get-UIA[ControlType] | Set-UIAFocus; Invoke-UIAHotkey "..."

depending on whether the contol support Set-UIAFocus or don't (UIA sometimes send a control to foreground without Set-UIAFocus).

Note: I didn't write all the keys it can support, only letters and numbers.

2) The Set-UIASendKeys cmdlet is just  System.Windows.Forms.SendKeys.SendWait(this.Text);

It accepts input, but it's not what you expect: for example, you send to it ten controls. It enumerates inputs and sends your keys ten times. It can send keys to a control as it also does not use handles.

It returns true if there was no error on sending text (sometimes, error may raise, if you are running application under very powerless user, for example, and the window process you are trying to work with is of higher privilege level).

3) The Set-UIAControlText cmdlet. If you need to put a text into a control and control has handle, it may be right choice. The cmdlet uses SendMessage to put the text you provided to a control with handle. Some third-party control may not support this.

4) The Set-UIA[ControlType]Text cmdlets use ValuePattern to set the text. Sometimes, third-parties support this pattern.

There are also specific API calls for controls derived from listview, listbox, treeview, and so on. I didn't create cmdlets for these (we simply never need).


If nothing of four options above is your result, I'd suggest you to run spy++ and find out what your control uses:

1) run spyxx.exe (VS 2010 or 2012)

2) Spy | Log Messages ... (Ctrl+M)

3) drag the Finder Tool and drop it onto your control

4) go to the Messages tab

5) There you may select all (very difficult to dig out the right result) or check Message Groups (a type of control, Keyboard and Mouse)

6) press OK and work with the control using mouse and/or keyboard

7) Messages | Stop Logging or F8

After that you need to learn what has happened when you did an action. After several attempts, one usually gets fast enough to start logging just by the time of manual test and stop it immediately after manual test. :)


Alternatively, you may ask the guy who writes the UI to create a new project with form, copy controls from your project and paste controls to a new form, and compile it. I.e., to make an empty, fake form, replica of your application. And put it somewhere on a web file share. I can try to learn what the control(s) is/are and how it/they work(s).