I'm trying to send a message to an application running under a different user account (a user that is also logged in with a different account on the computer, using quick user switch on XP and later, and executed the application).
The background is that my application can update itself, but in order to do that all running instances must be closed first.
The instances need to be shut down (instead of just killing the process), so the updater does that by sending a custom message to them (with SendMessage
). In order to send a message I need a handle to the main window of the process.
This works fine using EnumWindows
- as long as the instances are running under the same user account, because EnumWindows
does not list windows belonging to a different user.
So I tried a different approach. I used CreateToolhelp32Snapshot
to first list all running processes on the system, and then iterating through the threads calling CreateToolhelp32Snapshot
again. With those thread ids I could then list their windows using EnumThreadWindows
.
Once again this works fine, but.. once again only for the current logged in user. The problem here is that even though CreateToolhelp32Snapshot
lists process ids belonging to a different user it does not list thread ids belonging to them. The code for this is a little lengthy, but if it's required I can edit it in - please leave a comment for that.
So, how could I get the main window handle of my application running on a different logged in user account?
Use something that's known to work across sessions; This kind of stuff is often used for desktop-service communications, so look for that if you want to google. Here's my suggestion:
Global\
so it's valid across sessions.CreateEvent
function, pay close attention to the ERROR_ALREADY_EXISTS
non-error). That thread should simply wait for the event. When the event is triggered, send the required message to your main window. That thread can easily and safely do that because it's running inside your process. The thread will mostly be idle, waiting for the event to be triggered, so don't worry about CPU penalty.This is just one idea, I'm sure there are others.
Pipes are overkill. A global manual-reset event (e.g. "Global\MyApplicationShutdownEvent") which causes application instances to kill themselves should be enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With