Chris
Chris

Reputation: 3121

Sending a message to an application running on a secondary logged in user account

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?

Upvotes: 11

Views: 898

Answers (3)

Toby Allen
Toby Allen

Reputation: 11213

At the risk of being scoffed at, have you looked at zeroMQ, this is a perfect use for it and it very reliable and stable.

There is a Delphi wrapper

Upvotes: 0

Cosmin Prund
Cosmin Prund

Reputation: 25678

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:

  1. Create an event that will only be used to trigger the "need to shut down" state. Use the CreateEvent function make sure you start your name with Global\ so it's valid across sessions.
  2. On application startup create a thread that opens the named event (uses the same 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.
  3. Your application updateer should simply trigger the named event.

This is just one idea, I'm sure there are others.

Upvotes: 10

arx
arx

Reputation: 16896

Pipes are overkill. A global manual-reset event (e.g. "Global\MyApplicationShutdownEvent") which causes application instances to kill themselves should be enough.

Upvotes: 7

Related Questions