Sign in to follow this  
Followers 0

Session 0 isolation, Clicking on inactive windows, Running/Automating a GUI from Task Scheduler etc...

4 posts in this topic

This is just a summary of the various things I've learned over the past few days. There seems to be a lot of confusion regarding clicking/pressing a key in inactive/minimized windows. Possibly a better understanding of how Windows operates will help. So i'll start from here.

Any application window is all about forms and controls. Whenever a mouse is clicked or a key is pressed an EVENT is generated and sent to the application. How this event is sent is like this:

All relevant controls are sent events. For example if I click in a textbox within a window, an event is sent to the window as well as the textbox control. A developer may have chosen to handle the click from the textbox even rather than from the window event. This is why ControlSend/ControlClick to the main window often does not work. The developer may be handling the event from the control rather than the window. Hence use the Au3Info tool to get the control ID or other identifying parameters and experiment with sending the click or keypress to the control which responds to it.

I suspect *and I havent tested this hypothesis* but in Winspector Spy (where one can spy the events passed by the system to various windows and controls), if one selects capture events sent to parent and child windows also, I suspect one could get the entire set of messages generated by a keypress/click and sent by the system. if we send these same events (using PostMessage and DllCall) in the same sequence to the windows and controls, then I suspect we would have replicated Send/MouseClick for inactive/minimized windows.

For example scripts on sending events directly to the window/control see Check out the function _MouseClickPlus

For sending keypress events check out Check out the functions _SendMinimizedMessage _SendMinimizedVK and _GetHexByKey_Switch.

So to summarize use Winspector Spy to capture and then generate the exact sequence of events or get the relevant control identification using Au3Info and then do a ControlClick/ControlSend. Sometimes a control may not respond to a click, but might respond to a keypress... one needs to experiment to figure out what works.

Now the question may arise, why should I use ControlClick/ControlSend rather than Send/MouseClick? Well even if one is not developing gamebots (which may need clicking into minimized windows), a lot of GUI automating scripts may fail when the workstation is locked as Send and MouseClick get disabled by the system. So to get a script running and automating a GUI when the workstation is locked or another app gets focus before the script is through etc one needs to use ControlClick/ControlSend.

Automating a GUI from the task scheduler is the final part of my findings. The advantages are no one needs to be logged on to run the script. This involves certain complications. One needs to understand the Windows model presented very clearly in WinXP had a relatively less constrained model during which this difficulty did not arise. Vista onwards Windows introduced Session 0 isolation which basically prevented services (and related child processes) from interacting directly with any user's desktop.

See this image

Posted Image

Session 0 has two sessions [service-0x0-3e7$] and [Winsta0]. The Service-0x0-3e7$ (this number may be different on your system) does not have any graphical interface at all, Hence no GUI function will work here. By default task scheduler launches processes into this non-interactive session.

To get task scheduler to launch into the Session 0 -> Winsta0 interactive session two methods are recommended. Use the command prompt and schtasks.exe with the /IT switch to create a task. The GUI Task Scheduler does not have this option (at least on Win 7 and not on Vista also I guess).

The other option which I have used is to use Task Scheduler to launch PsExec.exe (Search google for PsTools/Sysinternals) with the -i option to launch the process into the Interactive services session of Session 0. Here all GUI commands will work normally. No need to use the AlwaysUp tool (paid tool) as recommended by various forums. Obviously the caveats above apply about workstation being locked etc.

If one has the interactive services detection service enabled, then one will get a message everytime a GUI is launched in this session. One can then switch to this session to debug if required. Hint: Launch a cmd prompt from task scheduler and psexec into this session and start explorer if required and it will look like any other normal session. If Interactive Services Detection service is enabled then one can also switch into this session by typing this into a command prompt rundll32 winsta.dll,WinStationSwitchToServicesSession.

Another promising app which dosent seem to work as promised at least for me is devxexec at, which claims to be able to launch an admin gui into a user session.

So thats it about automating GUIs, launching from the task manager and working around session 0 isolation on Win Vista and beyond.

Share this post

Link to post
Share on other sites

It was pointed out that this thread should be moved to chat because it's not specifically AutoIt related. I'm going to move it instead to Example Scripts even though there isn't a script here. It is a lot of useful information that unfortunately will go over most people's head.

Share this post

Link to post
Share on other sites

It was a good read, thanks for the informative post.

Share this post

Link to post
Share on other sites

#4 ·  Posted (edited)

Sometimes the TAB (and/or other keys may behave erratically. For example in an app I was working with one window handle received the WM_KEYDOWN for the TAB KEY, but then the app immediately activated a control within the window and this control received the WM_KEYUP for the TAB key.

I got this info by looking at the events in Spy++. You can get Spy++ from here I prefer to use this rather than Winspector Spy because it dosent require an install.

In Spy++, it is generally useful in Messages->Logging Options->Windows to select parent windows, child windows, windows of the same thread and windows of the same process. And in Messages->Logging Options->Messages de-select LVM_GETITEMW, LM_GETITEMCOUNT, WM_ENTERIDLE, WM_GETICON, WM_NCHITTEST, WM_SETCURSOR and WM_TIMER. Otherwise the log window gets badly cluttered, especially with WMNCHITTEST

Sometimes one wants to send just a WM_KEYDOWN or a WM_KEYUP. ControlSend will send both. So here is how to send it

$WM_KEYDOWN = 0x100
$WM_KEYUP = 0x101
$WM_CHAR = 0x102
$hwnd = GetWindowHandle("Notepad")
$skey = 0x09; TAB key
$ret = DllCall("user32.dll", "int", "MapVirtualKey", "int", $skey, "int", 0)
$lparam = BitShift($ret[0], -16)
$lparam = BitOr($lparam, 1)
DllCall("user32.dll", "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "int", $lparam)

Also sometimes one can get away with sending messages directly to a control though it may not necessarily in focus like a textbox for instance. The AutoIt spy tool does not always capture the control ID of all handles. To get control handles in spy++, click on Spy->Windows and search through that list to get your top level window.From here you can keep expanding the branches till you get the control and the control ID you require.

Edited by leunamme

Share this post

Link to post
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
Sign in to follow this  
Followers 0