tags:

views:

1248

answers:

3

I have an application that can list the opened windows of the current session. It uses the EnumWindows method from the user32.dll.

I would like to run this code from a windows service, but as the service is not attached to a user session, it returns nothing obviously.

So the question is, how can I enumerate the open windows of another user session (e.g. with a specific logon user)?

Similarly to EnumWindows, I also would like to get the foreground window of the user session as well (like GetForegroundWindow works for the current user).

+2  A: 

As far as I'm aware, you can't access the windows of one session from another. It's also worth noting that there's not really any such thing as "the current session" - there may be multiple users logged on through terminal services, or XP's fast user switching.

One approach to this would be to add a program to each user's profile with no UI that just communicates with your service. You'd still have to cope with the fact that there could be multiple active sessions, though.

DavidK
And, actually, for many reasons it's better to do all UI in those per-user applications, controlling them from the service through some kind of IPC.
atzz
+2  A: 

According to this document you can create a process in an other user's logon session using CreateProcessAsUser, and could enumerate the windows there. You will still need some IPC mechanism to communicate with the service.

csgero
Since I need to perform this call not only once, but regularly, I would end up with a service that immediately starts a user-session app in each interactive session. So I would end up with the solution that DavidK/atzz suggested (having a service-like hidden app). But good to know about it! Thx! ;)
Gaspar Nagy
+1  A: 

The accepted answer is not correct.

So the question is, how can I enumerate the open windows of another user session?

You can enumerate the open windows of any session if you're running as a service running as the local System account.

To do this first enumerate the sessions with WTSEnumerateSessions. Then enumerate the window stations inside each session with EnumWindowStations. Then enumerate the desktops for each Window Station with EnumDesktops. Finally you an enumerate the Windows in those Desktops with EnumWindows.

(e.g. with a specific logon user)

There can be many concurrent logged on users via Terminal services or fast user switching.

Similarly to EnumWindows, I also would like to get the foreground window of the user session as well (like GetForegroundWindow works for the current user).

This can be done by launching an app with a found user token in the Session, Window Station, and Desktop. From there you can call any Win32 API like GetForegroundWindow and report the info back to your parent process.

You can learn more about how Sessions, Window Stations, and Desktops work here.

Brian R. Bondy
This doesn't work: EnumWindowStations always enumerates the window stations for the current session.
Roger Lipscombe
@Roger: You start a process in each session before calling EnumWindowStations in each of those processes.
Brian R. Bondy
@Brian: You mention "This can be done by launching an app...", but my point is that you *can't* enumerate the window stations inside each session without it. You have to launch your helper app in order to do this. So: you *can't* "enumerate the open windows of any session if you're running ... as local system" -- without taking advantage of LocalSystem to launch a process as that user. This is too important a step to gloss over.
Roger Lipscombe