Just for background, my ultimate goal is to pass messages using
PostMessage from a service to GUI applications running not only on the
console but also in things like TerminalServices (or similar products
such as citrix or PCAnywhere or whatever). My question relates to
this, but if anyone knows a totally different approach that would be
welcome too.
I need to go from a process handle (or alternatively PID) to either a
window handle or thread handle. I've done some extensive searching and
everything I've found points to using either EnumWindows or FindWindow
if you need window handles. However, my code is operating as a
service, and I need to look through all the applications running on
the computer (even those running under different logins via things
such as Terminal Services). EnumWindows (and I believe FindWindow as
well, although I haven't confirmed this, currently writing some test
code) only iterates through windows in the current window station,
which for services is either no windows at all, or windows displayed
on the physical console (if you have "allow service to interact with
desktop" checked in the service's entry in service control panel). So
I don't think they will do the trick. I've tested the EnumProcesses
function from PSAPI and this does indeed allow you to access the
processes in other window stations. However I can't find anything in
PSAPI that allows you to get a window or thread handle, just process
handles.
If anyone happens to know if FindWindow has the same shortcoming as
EnumWindows, that would be helpful too, otherwise I won't know until I
finish the test code...
Alternatively, if someone knows a way to pass messages using process
handles, that would help.
TIA,
Dave
Ugh, I seem to have gotten closer but am not yet there... As a
followup, I've found two methods to get window handles or threadids in
this situation:
1. Get the ProcessID using PSAPI call EnumProcesses
2. Get a list of Thread IDs for that process using TLHelp32 call
CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
3. Post to threads using PostThreadMessage and ThreadID
*or similarly*
1.Get the ProcessID using PSAPI call EnumProcesses
2. Get a list of Threads for that process using TLHelp32 call
CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
3. Enumerate through all windows belonging to those threads using
EnumThreadWindows and use PostMessage on these windows
Both have positive results when my test code (right now in a GUI app
for easy debugging, to be moved to an actual service) is running on
the same desktop, but poor results when my test code is running on a
different terminal services session. In the first method using
terminal services, the thread in the recieving app doesn't seem to
recieve the message even though my test code can get the threadID and
sends the message. In the second method, the EnumThreadWindows doesn't
go through any windows.
> If anyone happens to know if FindWindow has the same shortcoming as
> EnumWindows, that would be helpful too, otherwise I won't know until I
> finish the test code...
I tested this and FindWindow has the same shortcoming.
> Alternatively, if someone knows a way to pass messages using process
> handles, that would help.
Crossing fingers...
TIA,
Dave
Just another tidbit of information, the last windows message in this
case is "Invalid Thread Identifier", which to me indicates that,
unlike ProcessIDs, ThreadIDs must not be valid across the whole
system, but instead only valid for a given windows station (or more
intuitively a given desktop station).
Dave
A final followup in case anyone in the future has this problem...
messaging, or cross process communication of any sort really, seems
pretty much impossible across the boundaries of a virtual desktop (at
least using built in win32 process communication structures such as
PostMessage, OpenSemaphore, etc). The PSAPI dll basically gives you
enough to implement whatever task manager does but nothing more.
Various handles and threadIDs and such you'd use for the communucation
are either not valid, impossible to get, or both. I even tried using
named mutexes, these don't work either across that boundary. I will
probably wind up just opening a network socket to localhost and
rolling my own form of communication. Ugh. Oh well, lesson learned.