I'm using the ServiceController class to start a (custom) installed service, like this:
var newServiceController = new ServiceController("theNameOfMyService");
newServiceController.Start();
Trouble is, the service always runs under the local system account, and instead I want it to run under my account.
Can anyone tell me how to use ServiceController to run a service under a different account?
I don't think you can... the credentials for the service are provided at install time or alternatively via the Service.msc snap in
The service controller can only start/stop a pre-installed service
On the ServiceProcessInstaller instance for you service there is a property called Acount, Password and Username, can use these properties to set who the service runs as.
Related
I want to implement an update service in my application (so users don't need admin rights to update my app once the service is installed, much like Google or Mozilla do their updates), and I think I found a good way to do this with WCF.
I have a WCFServiceLibrary-Project which contains the ServiceContract and the core functionality (download/install updates) and a Windows Service-Project which implements the WCFServiceLibrary as a Windows Service.
Additionally, there is a Visual Studio Installer-Project which installs the service and my application, which should be able to start/stop/communicate with the service using NamedPipes.
The service is configured to start manually with the LocalSystem-Account.
Now when the service is installed, I can start/stop it using services.msc (probably elevated), but not when I try it with net start Servicename (Error 5: Access denied) or with my application, which tells me that the local users probably don't have the permission to start/stop the service.
I need the service to run with higher permissions in order to perform the installation of updates, so I would like to give local users permission to start my service either during the first installation of the service or when the service starts for the first time (since I can trigger that also during installation).
However, how would I accomplish this with VB.NET (or C#)? I found some examples using API-Calls of advapi32.dll, but it didn't looks like the permission can be changed with this.
So, long story short, heres a summary of what I'm looking for:
Grant Group "Local Users" permission to Start my Service, best approach either during installation (Maybe with Custom Actions in Visual Studio Installer Project? Or in the ServiceInstaller-Class in the Windows Service-Project?) or the first time the service starts (OnStart-Event in Windows Service Project)
The service must not run with local user rights, since it would miss elevated privileges then which would be necessary to install updates.
I can't assign permissions through GPO/Local Policy since the users are not within our company, but all around the world. For the same reason I cannot assume that they can get an admin to elevate them everytime an update comes out.
I would like to avoid commandline calls if possible (as in assign permissions through command line, since those are most likely os-dependent)
Another solution would be to configure the Service as Automatic and Start it after install, but I don't like the idea that my service runs all the time since its only needed when my main application starts up.
Its most likely not a file permission issue. EVERYONE, SYSTEM and SERVICE got FULL ACCESS to the services folder and files in it.
There are already different similar questions here, but none did give a clear answer to this problem. One user probably did it using the WiX-Installer, but I would like to keep the Visual Studio Installer Project since it's pretty straight forward and easy to use.
After a bit more of googling and trying to find a "clean" solution, I've given up and using now Process.Start to execute sc.exe and set new Permissions after Installation.
Here's my ServiceInstaller-Class, for anyone curious:
[VB.NET]
Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.ServiceProcess
<RunInstaller(True)>
Public Class SvcInstaller
Inherits Installer
Dim svcprocinst As ServiceProcessInstaller
Dim svcinst As ServiceInstaller
Public Sub New()
svcprocinst = New ServiceProcessInstaller
svcprocinst.Account = ServiceAccount.LocalSystem
svcinst = New ServiceInstaller
svcinst.ServiceName = "KrahMickeySvc"
svcinst.DisplayName = "Mickey-Service"
svcinst.Description = "This Service is used by KRAH Mickey for application updates and maintenance"
Installers.Add(svcprocinst)
Installers.Add(svcinst)
End Sub
Private Sub SvcInstaller_AfterInstall(sender As Object, e As InstallEventArgs) Handles Me.AfterInstall
'Set new permissions acc. to Security Descriptor Definition Language (SDDL)
'Source: https://blogs.msmvps.com/erikr/2007/09/26/set-permissions-on-a-specific-service-windows/
'Keeping the source DACL and just adding RP,WP and DT (Start/Stop/PauseContinue) to IU (Interactive User)
Dim DACLString As String = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRCRPWPDT;;;IU)(A;;CCLCSWLOCRRC;;;SU)"
process.Start("sc.exe", $"sdset {svcinst.ServiceName} ""{DACLString}""")
End Sub
End Class
I have created a windows application that start\stop windows service
now when i tried to start\stop sq-server engine from my application it throw an exception
when i run my Application as administrator it works
now i can run my application as administrator using app.manifest but the problem is that my client does not have permission as administrator
what type of permission my Application need and how to do that?
public static void start()
{
ServiceController sc = new ServiceController(ServiceName, ServerName);
sc.Start();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
}
public static void stop()
{
ServiceController sc = new ServiceController(ServiceName, ServerName);
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
}
Your app is limited to the permissions of the person running it. If they don't have rights to do something, then neither will your application. You say that your client is not an administrator, so in order for your app to work for them an administrator will have to grant their login the permissions needed to start/stop services.
One of the following needs to happen:
The user needs to get admin rights
An admin needs to assign the user permissions to start/stop
services
Your program will need to be run under alternate credentials
For the 3rd option, this can be done at least a couple different ways:
Shift-right-click an application and it will give you a menu
option to run as another user. This option requires someone to be
there to enter their credentials every time you run the application
this way.
Add the ability for someone to enter their credentials into your
application and then impersonate them in your application when
starting/stopping services. This method would allow you to give
them the option to save their credentials for future use (not saying
that's a good idea though).
Normally when it is required to know the one of the service status in the existing server means it is easy by from finding the result from the servicecontroller by pasted below code:
ServiceController sc = new ServiceController("servicename");
if ((sc.Status.Equals(ServiceControllerStatus.Stopped)) ||
(sc.Status.Equals(ServiceControllerStatus.StopPending)))
{
// Start the service if the current status is stopped.
sc.Start();
}
Here i would like to know the service status of another machine, how can i find out the result can any one able to guide me on this scenario.
There's another constructor of ServiceController that takes the machine name as a second parameter. http://msdn.microsoft.com/en-us/library/ssbk2tf3.aspx
Have you tried it?
I'm writing the windows form program to monitor our in-house windows services.
The screenshot is provided for the draft version of that program.
What I want to do is... I want to pass UserName & Password to run the services from my program. I don't know which class or components to use.
I tried to use the following codes, as we used in Installing the services. However, it does not still work. Perhaps, I don't know how to bind the user credential with service controller.
ServiceProcessInstaller serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
serviceProcessInstaller1.Password = txtPassword.Text;
serviceProcessInstaller1.Username = txtUserName.Text;
So, Please advise me how could I achieve my requirements? Thanks.
Have a look at this library which lets you do just that:
Install a Windows Service in a smart way instead of using the Windows Installer MSI package
Since you are trying to manipulate the account that an existing, installed service is running under, you will need to use the code specified in the following article:
http://weblogs.asp.net/avnerk/archive/2007/05/08/setting-windows-service-account-c-and-wmi.aspx
Basically, the author found that it wasn't as simple as expected but it was possible (without a registry modification).
How do I enable "Allow service to interact with desktop" programmatically?
In services.msc > Action > Properties > Log On > Allow service to interact with desktop, I can enable my service to interact with the desktop. I want my service to play sound (MP3, WAV, etc.).
I'm going to take some liberties in here in trying to interpret your question from keywords. In the future, please spend more time writing your questions so that they make sense to another person who is trying to read and understand them.
There is a checkbox under the Log On tab in the properties window for a Windows service that is called "Allow service to interact with desktop." If you're trying to check that box programmatically, you need to specify the SERVICE_INTERACTIVE_PROCESS flag when you create your service using the CreateService API. (See MSDN).
However, note that as of Windows Vista, services are strictly forbidden from interacting directly with a user:
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 "feature" is broken, and conventional wisdom dictates that you shouldn't have been relying on it anyway. Services are not meant to provide a UI or allow any type of direct user interaction. Microsoft has been cautioning that this feature be avoided since the early days of Windows NT because of the possible security risks. Larry Osterman argues why it was always a bad idea. And he is not the only one.
There are some possible workarounds, however, if you absolutely must have this functionality. But I strongly urge you to consider its necessity carefully and explore alternative designs for your service.
Because the service does not run in the context of a user session, you create a second application to interact with the service.
For example, the Microsoft SQL server has a monitoring tool. This application runs in the user session and connects to the service providing you information on whether the service is running and allowing you to stop and start the database service.
Since that application does run in a user session, you can interact with the desktop through that application.
You need to add serviceinstaller and write down below code in commited event of serviceinstaller.
using System.Management;
using System.ComponentModel;
using System.Configuration.Install;
private void serviceInstaller1_Committed(object sender, InstallEventArgs e)
{
ConnectionOptions coOptions = new ConnectionOptions();
coOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope mgmtScope = new ManagementScope(#"root\CIMV2", coOptions);
mgmtScope.Connect();
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" + serviceInstaller1.ServiceName + "'");
ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
InParam["DesktopInteract"] = true;
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
}