I’ve got a project which has an application monitoring a set of applications through API’s.
If those applications to monitor become non responsive, I have a windows service that can take the request of the monitoring application to restart that non responsive application.
The applications that need to be monitored can also be run as a windows service, and if this is the case I have no issue whatsoever to stop the service and restart it.
However, if the applications that need to be monitored are running as an application with a GUI, I have to go out of my way to be able to start them from the windows service.
This is because since windows 7, Microsoft has introduced session 0 isolation, meaning the service can start an application with a GUI, but that GUI would never show in the current user’s session.
I’ve tried hijacking the current user’s token, starting the application with that token but that doesn’t work, and frankly I was way out of my depths because this was with C++.
In the end I’ve settled for creating a scheduled task that starts the application, but as soon as I stop that task the application shuts down as well. This has forced me to create a separate task for each application I’m restarting. It works, but I’m not 100% satisfied..
I was hoping someone here could point me to a way I haven’t tried yet, if there is any. Many hours spent Googling this.
Thanks in advance!
From a Windows Service, you can start a process in the user’s session using CreateProcessAsUser. As you say, this is Win32 API territory and much easier to do through native C/C++ than through C#.
There are some ways to avoid that problem – have two monitoring programs. One that runs in the user’s session and monitors/restarts the GUI apps within the session. And another that runs as a service, to restart the services. Although, it’s worth noting, the Service Control Manager already lets you restart services automatically on failure, so that may solve your problem for you.
As someone who knows both C# and C++ – I would find it easier to write just two separate C# programs 🙂 But if I had to do this from a Service, I would write the restarting part in C++ but expose it as a COM component to the C# service rather than deal with the p/invoke or native interop support in C#. But that’s purely a matter of opinion.
Thank you for your answer.
Having two monitoring programs is not really an option, I need one program to be able to handle both restarts (both service and application). I have dabbled with CreateProcessAsUser, but didn’t manage to get that doing what I needed unfortunately.
Sometimes the code in the service bugs out, it continues to ‘run’ but does not execute what it needs to do, so restarting services on failure is not an option either I think?
CreateProcessAsUser is the way to go, but it’s quite a complex task. There can be 3 different cases: no user logged, one user logged and more than one users logged and all cases must be taken into consideration. Could you post your code using CreateProcessAsUser?
I’ve already deleted that code because I couldn’t wrap my head around it unfortunately
CreateProcessAsUser is kind of a hard thing to do with .net, but it’s doable. Here’s a good StackOverflow post and the library that makes it easy, available as a package too, hides all the nasty advapi32.dll calls. I’m not honestly sure if and how it’s going to work with a UI application though.
Thanks for your suggestion, but looking at the library it needs to have the password for the user it needs to run as, which I don’t have.
I haven’t used CreateProcessAsUser yet that seems cool. The way I am doing it currently ist to deploy psexec with my library which allows me to start an application in any user session of a remote or local pc. Don’t know exactly how it works internally though because the target machine needs no setup for it to work. Also I list the available sessions via wmi.
So you get available sessions through wmi, then ask the user to select the user session to start the application on?
I’m working on something right now involving the same kinds of functions.
It’s a Remote Management Tool that, on occasion, needs to be able to run programs on remote computers, sometimes as local admin, and sometimes as whoever is the logged on user. I accomplish this by temporarily installing a service on those remote computers. You might be interested to know that psexec.exe, a very popular tool used to run programs on remote computers, uses this exact method (creating a service on a remote computer) to accomplish what we are both needing to do.
Services (as you likely already know) are special. They do run in session 0, but they are not limited to working ONLY in that session (as long as at least one user is logged on).
So, trying to keep this high-level, please look into a library available in NuGet called Cassia. Cassia is all about Windows Terminal Services and Windows sessions.
Next, and I will see if I can find the source (if I can, I will paste it in below) for how to get (and then impersonate, as others have been recommending to do with CreateProcessAsUser, a user token. Also, look into a series of API calls all starting with the letters WTS – here are a few of them:
WTSCloseServer
WTSConnectSession
WTSDisconnectSession
WTSEnumerateProcesses
WTSEnumerateProcessesExW
WTSEnumerateServers
WTSEnumerateSessions
WTSFreeMemory
WTSLogoffSession
WTSOpenServer
WTSQuerySessionInformation
WTSQuerySessionInformation2
WTSQueryUserToken
WTSRegisterSessionNotification
WTSSendMessage
WTSShutdownSystem
WTSStartRemoteControlSession
WTSStopRemoteControlSession
WTSTerminateProcess
WTSUnRegisterSessionNotification
Finally, I can’t find the source for which I was looking, but this might help instead: https://tocalai.medium.com/how-to-make-windows-service-interactivity-with-desktop-application-c36f3b5761fb