I need a certain process to be constantly running in every user’s computer. If that .exe is killed, I must be able to restart it and send an alert.
I immediately thought of building a Windows Service as the ideal solution, but I am facing a problem:
The process started by that service needs to be able to interact with the user, e.g. be able to show him a GUI.
my application also sets a keyboard hook in order to monitor the user's typing rhythms, and when I start the .exe from a service, that information is not accessible.
From the service I am able to launch the process "as the user" (using the LogonUser and CreateProcessAsUser functions), but still can’t see the GUI.
Is this possible? If not, what can I use to achieve the desired functionality?
tia
By default the GUI .exe will be run in the service session, which is separate from the interactive session of the user. You need to look into techniques for building an interactive service.
I've read a lot of similar questions on SO but haven't found an answer
I need to run a separate process from a windows service in logged in user's session but under system account, thus user cannot terminate the process
I need this process to interact with desktop for supervising purposes.
the main goal is to prevent user to terminate the process.
If you run an interactive applications (having GUI or not), from currently logged in user account - the end user (having Admin rights) may terminate the process. You either need to keep it as SYSTEM service, or remove all DACL/ACL information from the process using SetKernelObjectSecurity.
actually there's much simpler way to achieve the same: to prevent process termination by user w/o special privileges (like admin rights)
after long digging I found acceptable answer here: Prevent user process from being killed with "End Process" from Process Explorer
works fine if you're logged in as a regular user, you cannot kill the process from Process Explorer. Admin still can kill it because has sufficient privileges. it's exactly what I needed
I have a service which constantly checks some application and assures that it wasn't closed. If this app closed - service launches it again.
The problem starts when user decides to log off the session. During logoff all applications are closing including the mine one. But the service is still running and constantly trying to start it again.
The questions is how to notify the service that user is going to log off and the application doesn't need to be restarted anymore? I've tried to make it using SERVICE_CONTROL_SESSIONCHANGE notification. But in accordance to MSDN they come to services when all apps already closed and logging off procedure completed. It is too late for me. Is there any way to programmatically find out that current session is in process of logging off?
My service launched under LocalSystem account.
Thanks.
p.s. I don't have the access to application source code. The goal need to be achieved without modifying it.
Have your service run two applications: the one it is a watchdog for, and a second one which you implement yourself. This second one can then respond to the log-off event by sending a message to the service (a la David Heffernan's answer), and the service will then know not to restart the watched job.
Open a communication channel between your app and your service and arrange for the app to tell the service that it is closing because of a logoff event.
You may not have access to the source code of the executable, but that doesn't mean that you can't affect the process. For instance, you could inject a DLL. Using SetWindowsHookEx, you'd catch the WM_ENDSESSION sent to the apps main window.
Why don't you create your service under the user that is running the App and tell it to startup automatic? In this case you should get the SERVICE_CONTROL_SHUTDOWN message when your user is logging off since the service would also be terminated.
I need the ability in C++ code to logoff the console user when call from an administrator process or if it is called by that user and maybe a windows service in the future. The issue I am running into is that ExitWindowsEx will only logoff the user that calls it. If an administrator process calls a logoff the console user is unaffected. The only application that I know of that can do this is psShutdown.exe, except that psShutdown can only be run by the administrator. Does anyone know in C++ how to identify the console user and then do a logoff against that user? What is the magic inside psShutdown? I'm looking for something that works in WindowsXP and up. Also I cannot use WMI because some machines are running windows Embeded and do not have WMI.
(The reason psShutdown.exe must be run as administrator is because it installs a service and a normal user does not have the rights to do this.)
Use WTSGetActiveConsoleSessionId to identify the console session, but to go further you are going to need some permissions, you would have to call WTSQueryUserToken (You need to run as SYSTEM to do this) to get a token handle and then CreateProcessAsUser or impersonate and call ExitWindowsEx, or if you are not in a service, call WTSLogoffSession. (I tried calling WTSLogoffSession on my XP box and it did not work, probably because the terminal server service is not running on this system)
I have never actually done this, but it seems like it should be possible with the combination of WTSGetActiveConsoleSessionId() and WTSLogoffSession()
I have written a Windows service that allows me to remotely run and stop applications. These applications are run using CreateProcess, and this works for me because most of them only perform backend processing. Recently, I need to run applications that present GUI to the current log in user. How do I code in C++ to allow my service to locate the currently active desktop and run the GUI on it?
Roger Lipscombe's answer, to use WTSEnumerateSessions to find the right desktop, then CreateProcessAsUser to start the application on that desktop (you pass it the handle of the desktop as part of the STARTUPINFO structure) is correct.
However, I would strongly recommend against doing this. In some environments, such as Terminal Server hosts with many active users, determining which desktop is the 'active' one isn't easy, and may not even be possible.
But most importantly, if an application will suddenly appear on a user's desktop, this may very well occur at a bad time (either because the user simply isn't expecting it, or because you're trying to launch the app when the session isn't quite initialized yet, in the process of shutting down, or whatever).
A more conventional approach would be to put a shortcut to a small client app for your service in the global startup group. This app will then launch along with every user session, and can be used start other apps (if so desired) without any juggling of user credentials, sessions and/or desktops.
Also, this shortcut can be moved/disabled by administrators as desired, which will make deployment of your application much easier, since it doesn't deviate from the standards used by other Windows apps...
The short answer is "You don't", as opening a GUI program running under another user context is a security vulnerability commonly known as a Shatter Attack.
Take a look at this MSDN article: Interactive Services. It gives some options for a service to interact with a user.
In short you have these options:
Display a dialog box in the user's session using the WTSSendMessage function.
Create a separate hidden GUI application and use the CreateProcessAsUser function to run the application within the context of the interactive user. Design the GUI application to communicate with the service through some method of interprocess communication (IPC), for example, named pipes. The service communicates with the GUI application to tell it when to display the GUI. The application communicates the results of the user interaction back to the service so that the service can take the appropriate action. Note that IPC can expose your service interfaces over the network unless you use an appropriate access control list (ACL).
If this service runs on a multiuser system, add the application to the following key so that it is run in each session: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. If the application uses named pipes for IPC, the server can distinguish between multiple user processes by giving each pipe a unique name based on the session ID.
WTSEnumerateSessions and CreateProcessAsUser.
Several people suggested WTSEnumerateSessions and CreateProcessAsUser. I wonder why no one suggested WTSGetActiveConsoleSessionId, since you said you only want to target one logged in user.
Several people sure are right to suggest CreateProcessAsUser though. If you call plain old CreateProcess the way you said, then the application's GUI will run with your service's privileges instead of the user's privileges.
That problems Session 0 , Interactive Services ,
Windows Service Allow Service To Interact With Desktop
on Windows 7 or Windows Vista
You can read this article
http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx
I try explained here it's working on Windows 7
On Win2K, XP and Win2K3 the console user is logged on in Session 0, the same session the services live in. If a service is configured as interactive, it'll be able to show the UI on the user's desktop.
However, on Vista, no user can be logged on in Session 0. Showing UI from a service there is a bit trickier. You need to enumerate the active sessions using WTSEnumerateSessions API, find the console session and create the process as that user. Of course, you need also a token or user credentials to be able to do that. You can read more details about this process here.
I think as long as you have only one user logged in, it will automatically display on that user's desktop.
Anyway, be very careful when having a service start an exe.
If the write access to the folder with the exe is not restricted, any user can replace that exe with any other program, which will then be run with sytem rights. Take for example cmd.exe (available on all windows sytems). The next time the service tries to start your exe, you get a command shell with system rights...
If you launch a GUI from your service it will show up on the currently active desktop.
But only if you adjusted the service permissions: You need to allow it to interact with the desktop.
Important Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.
This is taken from : http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx