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'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).
I'm getting this error when I try to start a windows service I've created in C#:
My Code so far:
private ServiceHost host = null;
public RightAccessHost()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
host = new ServiceHost(typeof(RightAccessWcf));
host.Open();
}
protected override void OnStop()
{
if (host != null)
host.Close();
host = null;
}
Update #1
I solved the issue above by granting permissions to the account NETWORK SERVICE but now I have an another problem:
Update #2
Service cannot be started. System.InvalidOperationException: Service 'RightAccessManagementWcf.RightAccessWcf' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
at System.ServiceModel.Description.DispatcherBuilder.EnsureThereAreNonMexEndpoints(ServiceDescription description)
at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
at System.ServiceModel.ServiceHostBase.InitializeRuntime()
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at RightAccessHosting.RightAccessHost.OnStart(String[] args) in C:\Users....
I realize this post is old, but there's no marked solution and I just wanted to throw in how I resolved this.
The first Error 5: Access Denied error was resolved by giving permissions to the output directory to the NETWORK SERVICE account.
The second Started and then stopped error seems to be a generic message when something faulted the service. Check the Event Viewer (specifically the 'Windows Logs > Application') for the real error message.
In my case, it was a bad service configuration setting in app.config.
Computer -> Manage -> Service -> [your service] properties.
Then the the tab with the account information. Play with those settings, like run the service with administrator account or so.
That did it for me.
EDIT:
What also can be the problem is that, most services are run as LOCAL SERVICE or LOCAL SYSTEM accounts. Now when you run C:/my-admin-dir/service.exe with those accounts but they are not allowed to execute anything in that directory, you will get error 5. So locate the executable of the service, RMB the directory -> Properties -> Security and make sure that the account the service is run with, is in the list of users that are alloewd to have full control over the directory.
This worked for me.
Right-click on top-level folder containing the service executable. Go to Properties
Go to "Security" Tab
Click "EDIT"
Click "ADD"
Enter the name "SYSTEM", click OK
Highlight SYSTEM user, and click ALLOW check-box next to "Full control"
Click OK twice
Make sure the Path to executable points to an actual executable (Right click service -> Properties -> General tab).
Via powershell (and sc.exe) you can install a service without pointing it to an actual executable... ahem.
I also got the same error , It resolved by
Right click on Service > Properties >Log On > log on as : Local System Account.
I was getting this error because I misread the accepted answer from here: Create Windows service from executable.
sc.exe create <new_service_name> binPath= "<path_to_the_service_executable>"
For <path_to_service_executable>, I was using the path of the executable's folder, e.g. C:\Folder.
It needs to be the path of the executable, e.g. C:\Folder\Executable.exe.
I got the solution:
1. Go to local service window(where all services found)
2. Just right click on your service name:
3. click on "properties"
4. go to "log on" tab
5. select "local system account"
6. click "ok"
now you can try to start the service.
In my case following was not checked.
if you are a having an access denied error code 5. then probably in your code your service is trying to interact with some files in the system like writing to a log file
open the services properties select log on tab and check option to allow service to interact with the desktop,
For me - the folder from which the service was to run, and the files in it, were encrypted using the Windows "Encrypt" option. Removing that and - voila!
This error happens when there is a error in your OnStart method. You cannot open a host directly in OnStart method because it will not actually open when it is called, but instead it will wait for the control. So you have to use a thread. This is my example.
public partial class Service1 : ServiceBase
{
ServiceHost host;
Thread hostThread;
public Service1()
{
InitializeComponent();
hostThread= new Thread(new ThreadStart(StartHosting));
}
protected override void OnStart(string[] args)
{
hostThread.Start();
}
protected void StartHosting()
{
host = new ServiceHost(typeof(WCFAuth.Service.AuthService));
host.Open();
}
protected override void OnStop()
{
if (host != null)
host.Close();
}
}
I had windows service hosted using OWIN and TopShelf.
I was not able to start it. Same error - "Access denied 5"
I ended up giving all the perms to my bin/Debug.
The issue was still not resolved.
So I had a look in the event logs and it turned out that the Microsoft.Owin.Host.HttpListener was not included in the class library containing the OWIN start up class.
So, please make sure you check the event log to identify the root cause before beginning to get into perms, etc.
In my case, I had to add 'Authenticated Users' in the list of 'Group or User Names' in the folder where the executable was installed.
One of the causes for this error is insufficient permissions (Authenticated Users) in your local folder.
To give permission for 'Authenticated Users'
Open the security tab in properties of your folder, Edit and Add 'Authenticated Users' group and Apply changes.
Once this was done I was able to run services even through network service account (before this I was only able to run with Local system account).
Right click on the service in service.msc and select property.
You will see a folder path under Path to executable like C:\Users\Me\Desktop\project\Tor\Tor\tor.exe
Navigate to C:\Users\Me\Desktop\project\Tor and right click on Tor.
Select property, security, edit and then add.
In the text field enter LOCAL SERVICE, click ok and then check the box FULL CONTROL
Click on add again then enter NETWORK SERVICE, click ok, check the box FULL CONTROL
Then click ok (at the bottom)
Your code may be running in the security context of a user that is not allowed to start a service.
Since you are using WCF, I am guessing that you are in the context of NETWORK SERVICE.
see: http://support.microsoft.com/kb/256299
I have monitored sppsvc.exe using process monitor and found out that it was trying to write to the HKEY_LOCAL_MACHINE\SYSTEM\WPA key. After giving permissions to NETWORK SERVICE on this key, I was able to start the service and Windows suddenly recognized that it was activated again.
Use LocalSystem Account instead of LocalService Account in Service Installer.
You can do this either from doing below change in design view of your service installer:
Properties of Service Process Installer -> Set Account to LocalSystem.
or by doing below change in in designer.cs file of your service installer:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
Have a look at Process Utilities > Process monitor from http://www.sysinternals.com.
This is tool that allows you monitor what a process does. If you monitor this service process, you should see an access denied somewhere, and on what resource the access denied is given.
For the error 5, i did the opposite to the solution above.
"The first Error 5: Access Denied error was resolved by giving permissions to the output directory to the NETWORK SERVICE account."
I changed mine to local account, instead of network service account, and because i was logged in as administrator it worked
If you are getting this error on a server machine try give access to the folder you got the real windows service exe. You should go to the security tab and select the Local Service as user and should give full access. You should do the same for the exe too.
I accidentally set my service to run as Local service solution was to switch to Local System
After banging my had against my desk for a few hours trying to figure this out, somehow my "Main" method got emptied of it's code!
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new DMTestService()
};
ServiceBase.Run(ServicesToRun);
Other solutions I found:
Updating the .NET framework to 4.0
Making sure the service name inside the InitializeComponent() matches the installer service name property
private void InitializeComponent()
...
this.ServiceName = "DMTestService";
And a nice server restart doesn't hurt
Szhlopp
In may case system run out of free space on local disk.
I had this issue today on a service that I was developing, and none of the other suggestions on this question worked. In my case, I had a missing .dll dependency in the folder where the service ran from.
When I added the dependencies, the issue went away.
In my case I kept the project on desktop and to access the desktop we need to add permission to the folder so I simply moved my project folder to C:\ directory now its working like a charm.
I don't know if my answer would make sense to many, but I too faced the same issue and the solution was outrageously simple. All I had to do was to open the program which I used to run the code as an administrator. (right-click --> Run as Administrator).
That was all.
check windows event log for detailed error message. I resolved the same after checking event log.
All other answers talk about permissions issues - which make sense, given that's what the error message refers to.
However, in my case, it was caused by a simple exception in my service code (System.IndexOutOfRangeException, but it could be anything).
Hence, when this error occurs, one should look inside their log and look for exceptions.
I had this issue on a service that I was deploying, and none of the other suggestions on this question worked. In my case, it was because my .config (xml) wasn't valid. I made a copy and paste error when copying from qualif to prod.
I have an issue with a Windows Service which throws a NullReference exception whenever I try to use
var myType = Activator.CreateInstance(typeof(MyType))
There is no problem whenever I run the exact same code in a console window - and after debugging the obvious "which user is running this code" I doubt that it is a mere fact of changing the user running the service as I've tried to run the service using the computer's Administrator account as well as LocalSystem. I'm suspecting a Windows Update fiddling with default user rights but that's a bit of a desperate guess I feel.
Remember: The type and assembly exist and works fine - otherwise I wouldn't be able to run the code in a console window. It is only when running in the context of a Windows Service I get an error.
The question is: Can I in any way impersonate i.e. LocalSystem in a unittest by creating a GenericPrincipal (how would that GenericPrincipal look)?
You could always run a visual studio instance as LocalSystem. From the command line, enter the following:
at <time in near future> /interactive <path to devenv.exe>
Then wait for that time to roll around and VS should open up, but will be running under the LocalSystem account.
I'd personally not suspect the user account, and instead suspect that it's something to do with being interactive - does the constructor or class constructor for MyType have some implicit dependency on the desktop?
(Edit - oops, should be time before /interactive, corrected command line).
e.g.
at 11:48 /interactive "c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe"
I know its a simple answer but have you tried putting it in a try catch block then writing out the exception to see if it is Permission based or otherwise.