How can i prompt for password and user when someone tries to stop a windows service?
It cannot be done.
Services are meant to run outside the user experiance and do not handle GUI interactions. This is something that is left up to the operating system to allow or disallow a user from stopping a service.
It cannot be done directly from the service. However, the service can be managed by another application if the service is set to interact with the desktop. So you could create a second application with a GUI that monitored the service. The service could set some value in shared state file when the services 'Stopping' event fires and wait until the monitoring app writes a confirmation value in the state file. Maybe not what you are looking for exactly but I think you could get the result that you want.
Ordinarily, there's no reason to do this. By default, only administrators can stop a service, and if the service can be stopped at all it makes no sense to ask an administrator for a password to do so: they're an administrator, so by definition they're entitled to do anything.
The one scenario that makes sense is if you want ordinary users to be able to stop the service if they know the password. That way, you can let someone stop the service without giving them administrative rights to the computer. (Even then, in most cases it would be simpler to change the permissions on the service to allow the user(s) in question the right to stop the service; but perhaps, for example, you want users to be have to phone a helpdesk to be given the password.)
The secret to making this work is that the service is entitled to stop itself for any reason without having received a stop request from the operating system. So you can just write a program that the users can run if they want to stop the service. The program accepts the password and sends it to the service over some form of IPC, such as a named pipe. If the password is correct, the service stops.
You could also configure the service so that it doesn't accept stop requests, in which case an administrator would also need the password in order to stop the service nicely. But that wouldn't stop them from stopping the service by killing the service process, or uninstalling the service and rebooting the computer.
Related
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
So I created a Windows Service using C# and created an installer in Visual Studio for it. It's set up to run manually as I don't want it running all the time. I then have another application (C# WPF) that should have an option to turn the service on and off (the service itself creates a web service that in turn communicates back to my WPF application). This works fine in Windows XP, but testing it on a Windows 7 machine, it won't start. Surprisingly it does throw an exception and crash, it just does nothing. I believe this is a permissions problem. If I go to the services control panel using the same Windows 7 account, I'm not able to start or stop the service either.
So my question is, is there a way to set my service so that regular user accounts can start and stop it? And is there a way to set my installer to do this automatically.
I don't want my WPF application to have run as administrator!
Whilst I believe that it is possible to secure a service so that regular users can start and stop it, I do not recommend doing so. This will create a lot of complication and is a potential cause for confusion. I always prefer to keep things simple, especially when it comes to installation and security.
So, if we can't let the user start and stop the service we probably need to let the service run all the time. Since you don't want the service to be active all the time I suggest you give the service its own internal Running flag. When this is set true, the service is active and does busy things, otherwise the service remains idle. You can use your preferred IPC mechanism (sockets, named pipes, WCF etc.) to allow the user to toggle this switch.
Windows 8 has a feature to allow services to start on demand, basically in response to some kind of trigger. But for Windows 7, your only real option is to set it to start automatically on startup. You could set it to start delayed, so that its not adding to the time it takes windows to start.
Regular users cannot start and stop services.
EDIT: Reading the link in the comment above it sounds to me as that is a blanket ability for users to start and stop services. I think the question here is about how to do this for a particular service.
Also, while it may be possible to set the service to run as that particular user, it really means it only works for that particular user and other users on the work station would not be able to use the application as they'd not be able to start or stop the service, assuming that the service running as a user implies that the user may control it, which may not be the case.
Also in reading the comments and other answer, I'm left to wonder if the service can be used by any user which can run the application. That is, if user A logs on to the work station and starts this app (and thus the service), locks it and walks away, what happens when use B logs on and tries to run the same service? Can the service support multiple users at the same time, or will funny things begin to happen if the service is utlized by the application running multiple times.
This really sounds like what is desired is for a background to be started when the application starts. This thread (or threads) would do the work of the service, and by their nature would end when the application ends. Of course more detail in the question would help give a better answer.
Of course if it is appropriate as a service, I see no reason not to have a service with a worker thread that sleeps, and another timer thread that acts as a producer that checks if there's work to do.
i have developed the window service. in this i want to start the service only when starting the computer. user can not start/stop/restart the service.manually these all thing are handle when user start the computer.
or lock the all properties from the user.all working done by coding when we start the computer.
There are two ways to accomplish this that I can recommend.
Permissions. Normal users should not have permissions to start/stop services. If they do and are not administrators, you can at least remove permissions to start/stop the particular service you want to protect. http://msmvps.com/blogs/erikr/archive/2007/09/26/set-permissions-on-a-specific-service-windows.aspx
Restart. You can have a scheduled task to automatically restart the service if it is stopped. Again, you can use permissions to make sure the scheduled task is not modified. You can even run the task remotely as long as the target computer is on the network.
Would you want some software installed on your PC to prevent you from starting or stopping it and just automatically forcing it to run....? I don't think so, this is a bad idea and am pretty sure security settings in windows will not allow this...
Are there situations that we should use a windows service ?
I am building a client-server project (c#) and the server supposed to work alone without any user so someone advised me to use a windows service to run the server, is this right ? or there are a better solutions ?
Windows services are normally used when an application needs to continuously run. For example if they need to:
Wait for incoming requests. (Like through remoting or wcf)
Monitor a queue, file system etc.
If a program just needs to run periodically, like once a day. It is normally easier to create a scheduled task.
In your situation I would use a service for the following reasons:
You don't need to have a session running. This is good for security, and also reduces overhead on the server.
You get some of the managment commands built in for free
Start
Stop
Pause
Continue
You can handle server events such as shutdown.
Windows service can start running as soon as the machine is powered up, which makes ideal for running as a server, http server for example. No one is required to login.
You should create a Windows Service to run code in the background, without user interaction.
For example, a Windows Service will run even if no-one is logged on.
Any server that accepts connections (such as a mail, web, or FTP server) should usually be a Windows Service.
Well, a Windows Service provides a full framework for your application to work and to remain active while you want it to, so I think its ok.
Windows services are the right thing to use for something that should run all of the time, whether or not a user is logged in.
If you need something to run without an active user logged in, you need to use a windows service.
When you need the application to start running even when no one has physically logged into the machine, which is common with server machines, a service is a good candidate in this case. Especially because the service can be configured to auto start, which means the service will start when the machine is rebooted withut human intervention.
If however you are wanting to host web services (WCF) while a service is an option, you might consider hosting in IIS, this relieves you of writing the actual hosting code etc.
I am writing an application in C# that needs to run as a service but also have user interaction. I understand that services have no UI, etc, so I've divided up my program into a windows form application and a service that can communicate with each other.
The problem I'm having is that I need the service to make sure the windows form application is always running and restart it if it is not. I'm able to detect if it is running, and restart it with the following code on Windows 2000/XP:
System.Diagnostics.Process.Start("ExePath");
but on Vista, it runs the new process as a Local/System process which is invisible to the user. Does someone way around this? Is there some way to detect which user is currently logged on and run the new process as that user? I don't need to account for fast-user switching at this point. Something - anything - basic would suffice.
I would be grateful for any help or tips you have on the subject.
I need to clarify that I am setting the "Allow service to interact with desktop" option when the service is installed. This is what allows it to work on 2000/XP. However, Vista still has the aforementioned problem.
The general idea for this sort of thing is, if the user needs to interact with a service, they should launch a separate application. If you want to help them out, you can configure that separate application to start with windows by placing a shortcut in the start up menu. You can also build crash recovery into your application so it can automatically restart.
You shouldn't really rely on monitoring the forms application, what if no one is logged in? What if multiple people are logged in? It just gets messy doing things this way.
Having the service just sit there and broadcast to listeners is the way to go. When the forms application starts it can notify the service it wants to listen to events.
See the question: How can a Windows Service execute a GUI application?. It addresses the same question from C/C++ (short answer: CreateProcessAsUser), but the answer's still valid (with some P/Invoke) for C#.
In this case, you will have to have a third monitor process which detects if the program fails and restart it in that case.
However, you end up with an unsolvable problem here, as the monitor process will have to be watched to make sure it doesn't get shut down, and so on, and so on, and so on.
You might want to reconsider this approach.
Its a tough situation. As mentioned in a couple places, if you must have a UI then technically you shouldn't be using a service. Afterall, services run without a user even logged on. If nobody is logged in, you cannot have a UI.
Normally, when I need a service needs to communicate with the outside world, there are two things I opt for. I can either place an entry in the event log, or I can drop a message in a queue.
In your case I'd use a queue. When a user logs in, you can auto start an app for them that monitors the queue. If the app is running, when the message is received, they are alerted that way as well. However, if the user closes the app then the same thing occurs... they won't know.
First, a quick answer: Does the 'Allow service to interact with desktop' option (service -> Properties -> LogOn) or specifying an account allow what you're wanting? If so, both of these can be configured on your service installer class.
Like the others, I suspect there is a better approach to this and either one of the following is true:
-The code inside the service could be included in the winforms app (perhaps running in a background thread), and added to windows startup. Both will be running
-The winforms app can just listen to the service when it's on, and doesn't need to be started from the service. Or similarly, the app could be added to startup.
To have your service run the application as a user (which seems to be what you are trying to do) you need to do the following:
System.Security.SecureString ss = new System.Security.SecureString();
foreach (char c in password)
ss.AppendChar(c);
System.Diagnostics.Process proc = Process.Start(path, arguments, username, ss, domain);
Where:
path = full path (including filename) of the executable.
arguments = string of arguments (use an empty string is none)
username = The name of an user account on your server/computer
domain = your network domain (if your using a network account- blank if none)
Also, In order for your service to have permission to launch an application, it must be running as a service also. To do this, you need to add these lines to your service installer class:
serviceProcessInstaller.Account = ServiceAccount.User;
serviceProcessInstaller.Username = "yourdomain\\yourAccountName"; //Or just "AccountName" for local accounts..
serviceProcessInstaller.Password = "yourPassword";
In Windows 2000 and XP, there is an option (checkbox) on the Logon tab of the service properties window to allow the service to interact with the desktop. I believe this is what you are looking for. I just wrote a quick service in VB.NET with a Process.Start("calc.exe") and Windows Calculator opened just fine.
I'm not 100% sure this works the same way in Vista though.
Sounds like you might not need half of it running as a service (unless there's a requirement of higher privileges), as your service would need to cope with when there is no interactive user logged on as well.