I have a very critical process that will run on the background in my winform application.
How can I prevent the user to end my winform application process?
I want to prevent the user to:
end the process from the Task Manager
shutdown the computer before the process of my application end
any other software-related method to kill a process (of course I cannot prevent the user from pressing the power button of his CPU)
My code is in C#, framework 4, build in VS2010 Pro.
Thanks in advance.
Stating your 'absolute' need to keep this process running, I really suggest to separate the critical part of your process from your winforms application and to move this part away from the user machine to a company server.
On this server write a service which keeps your vital work alive and running all the time you like.
These kind of 'absolute' requirements could be enforced only on server machines with redundancy disks, ups units and, (especially), informed sysadmins.
It's basically impossible to stop users from killing processes (you can even kill explorer.exe which is the shell for windows).
So it's recommended that you write your applications in such a way that they are resilient to user action or crashing. In your case it would be wise to have resumable operations in that process.
You can't absolutely ensure these things, but you can get some of what you want by:
1) Run only on Vista or later versions of Windows that assign security levels to processes
2) Run your process as administrator so it is the highest security level.
3) Make sure UAC (User Account Control) is turned on.
4) Turn off access to task manager for the logged in user account (via group policy)
5) Provide no way for the logged in user to elevate to admin, so that he can't run anything that has the privileges to stop your process.
6) Use a Shutdown script to check for your process running and prevent shutdown.
Related
We are developing a .net application to run on startup for all users. Now we want to hide this application from task manager -> process list so that logged in user cannot delete it. We are using windows-xp
Please let me know if this is feasible
It's definitely possible to hide a process; you're talking about designing a rootkit. If that's actually what you want to do, see this question.
It's usually not the right way to approach this problem however: if you're the admin of a machine and you don't wish other users to kill a process, you simply don't give them permissions to do it.
Have your users log on with a limited user account and have your application run under a different account.
To get logon time reliably, you can use some either the windows security logs or if you're on a domain, active directory services:
Getting Local Windows User login session timestamp in C#
Getting idle time is more complicated because it depends on what you consider "idle" to be, but if you consider GetLastInputInfo() sufficient, this question describes a good way to do it, with a user process reporting back to a system process:
Getting user Idle time in C#?
Since the user cannot kill the system process, you could have that watch the user process and recreate it if necessary.
That's what Windows security is for. Define user account's permission in a way that he/she cannot manage services or kill processes.
If the case is as you described in comments under Colin's answer, then you can run a service-level process that respawns user process every time it is killed (by user). This way it is even simplier. You can use CreateProcessAsUser from WinApi to execute process on behalf of the user: http://msdn.microsoft.com/en-us/library/ms682429%28v=vs.85%29.aspx
Hide it in plain sight : make it run as a service with name that looks like it should be part of windows.
Then have another service that watches for the this one shutting down and restart it.
I have one major problem with my app. I have an app & updater as a separate exe files. When an update is available, updater does the update, and on process completion it starts my app. The main problem is - app is installed in program files folder, so updater need UAC admin privileges, and that's ok, but when I need to run my app updater needs to run it as a normal user, because if it's run as an administrator drag and drop doesn't work (not an app problem, UAC blocks it). I've tried several different solutions, and even this one:
How to run NOT elevated in Vista (.NET)
It haven't helped me - my app is run as an administrator.
You'd better avoid starting a non-elevated process from an elevated one. It's tricky part and error-prone.
This approach is better:
Your updater initially starts as non-elevated application, and its manifest has asInvoker level.
When it starts, it restarts itself with elevated privileges using runas verb, and passes a command-line parameter to indicate it. This instance performs the update and returns.
Here comes the non-elevated updater again, and starts your application with the same non-elevated user token that started the first instance of updater in step 1.
Pretty simple and robust.
Look at this post on how to Enable Drag and Drop for an Elevated process. Even though it says MFC app you can cll those Windows API in Any app I suppose
https://helgeklein.com/blog/2010/03/how-to-enable-drag-and-drop-for-an-elevated-mfc-application-on-vistawindows-7/
At the moment we have .NET WinService started under LocalService user at windows start. The service launch another WinForms Application using Process.Start().
But there are several problems in this solution:
We don't wait for an interactive user logon and the Application falls because it tries and fails to initialize DirectX device.
Application launched under LocalService perfectly interacts with user desktop in Windows XP. But it doesn't work in Windows 7 because of there are different graphic stations for each user in win7.
Sometimes we need to run application with current interactive logon user rights.
Does anybody know how to wait for user interactive logon in the service and start WinForms Application with these user rights?
I think this helps to solve all problems.
You will need a separate client app. Check out this document, page 6: http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspx.
For your monitoring/restart scenario look at CreateProcessAsUser as mentioned in the document. You will almost certainly need to have your client app coordinate with the service for this, and it's still pushing a square peg into a round hole.
I would try using a combination of the answers above.
To solve #1
At user logon, launch the Winforms application using autostart in registry or startup folder. Make it notify the service that it was started successfully.
To make sure that the Winform app is started successfully after user log on:
Have your service that checks if application is started running in the background as you have now but don't let it do the initial startup.
Instead just let it register when user logs on, should be possible to do by listening to OnSessionChange.
Set a delay for X number of seconds to allow the login/startup process finish before it starts checking for a running application (ok maybe not the best solution).
If the service discovers that the application is not started or crashes, restart it from the service using the method Mark points out, CreateProcessAsUser.
Is it possible that this just isn't the right approach for what you're trying to do? It seems possible that you'd be better off putting the monitoring logic or whatever has the uptime requirements into the service so that it's "always on" so to speak. Then you would be left with UI logic in the WinForms app, which could be open or closed with no ill effect.
This is the scenario:
I have a service (#1) running as LOCAL SYSTEM, and it will eventually run a process (#2) that updates an application (#3). This process (#2), the updater, must run as LOCAL SYSTEM also, no problem here, since it needs to rewrite some files (#3).
When the updater starts as LOCAL SYSTEM, it will kill any running instance of my application (#3). After the files being update, I need to start the updated application (#3) again as the current logged account.
How could I manage this? Is there anything conceptually wrong in my idea?
UPDATED
The updater kills the app just to replace the files.
I don't think there's a way for the service to get its hands on the WindowsIdentity.Token handle it would need to call the CreateProcessAsUser() API function. Unless the app itself provides it.
There's a better way, you don't have to terminate the app to replace its executable files. All you have to do is rename them. You can then put the updates in place and signal the app to restart itself. Another nice advantage of this approach is that the app voluntarily shuts down (including notifying the user) instead of getting rudely aborted. Clean up the renamed files when you see the process terminated.
If you have access to the user's credentials, you can use Process.Start with a ProcessStartInfo specifying the username and password of the user.
If you don't know the credentials, then I am not sure it can be done.
A work around could be to have the service communicate with your program, asking it to shutdown itself, but before doing so, it should start a seperate tiny program. This should be running in the background, but it will be running with the current user's credentials. When you are finished, ask the background program to start your main program again, then exit.
One problem is knowing the "logged in user". XP and up support fast user switching, where more than 1 user may be logged on at the same time (vista and up support this feature even if the machine is a domain member).
Here is a link to a Raymond Chen blog article discussing the issue: http://blogs.msdn.com/oldnewthing/archive/2006/08/22/712677.aspx
At my company we have a product which pretty much interacts with everything you can imagine... registry, databases, devices, etc... it is composed of many parts but the entire application is launched by a single executable (start.exe) which is responsbile for launching everything else - this is all legacy code and run under a USER account.
Currently this is launched as a STARTUP item (or by double-clicking on the desktop icon) in Windows, meaning when the user logins into the USER account the application (start.exe) automatically kicks off, under this account it has all the permissions it needs to run and everything has been fine for years...
Now comes the change - I have written a service (Serv.exe) that is running as LocalSystem - this service is responsible for updating the various software components of our product and works as follows:
- when the product detects an update it signals the LocalSystem service (Serv.exe) and then terminates itself
- Serv.exe will then perform all the updating
Now, after everything is done, the product (via start.exe) needs to be launched again automatically ... and this is where I need some advice ... what is the best way to restart the product (start.exe)?
Right now I use the LocalSystem Service (Serv.exe) and impersonate the USER account as follows:
- CreateEnvironmentBlock for the USER
- CreateProcessAsUser(start.exe) as the USER with the corresponding EnvBlock
- DestroyEnvironmentBlock
But is this really 100% equivalent to double-clicking on the icon in the USER account context? I need to ensure that everything is identical when it is either launched on STARTUP of USER or by Impersonation from Serv.exe (LocalSystem) - is there a risk involved? Will I still have the same rights/abilities with all databases? registry? device interaction? etc..
By loading the EnvBlock I seem to get everything I need but ... is this not a good way to do it...?
Kind of hoping for some guidance and advice from the pro's out there ...
Any help or hints would be much appreciated.
Thanks,
Update: Here is a post named: Launching an interactive process from Windows Service in Windows Vista and later. Which is exactly what you are looking for. It starts with:
The first thing you should do about it is that; don't do it. There are many limitations and bad implications and restrictions involved.
So first test if your current solution works. That depend on what the process is doing. If it is not involving user interaction. Or manipulating the current user session. Then you don't need this complex solution. If you need it, than good luck!
Before update: Its not 100% equivalent. Except authorization there are, in windows, sessions and, in each session, there are desktops. The process that is lunched from the service will run on the service session and desktop ( if the service has it). Depending on what the start.exe does, it may be important or not.
Look at the SetTokenInformation function.
Instead of launching the application directly as a "startup item" you could start a "launcher.exe" that then would launch your application. The service could then signal "launcher.exe" that another instance of the application should start after an update. Using this method you can't use the service to update "launcher.exe", but this executable should be very simple and hopefully not require any updates. Using this method would avoid all the pitfalls of trying to start an interactive application from a service.