problems starting a Network service

S

sunil

Hi,
I have a service written in c# that I need to run as a "Network
Service". I am using a setup project to install the service.
If I install the service in User's Personal Folder, I get the following
error:
"Could not start the <servicename> service on Local Computer. Error 5:
Access is denied."

If I install the service in ProgramFiles folder, I get the following
error:
"The <servicename> service on Local Computer started and then stopped.
Some services stop automatically if they have no work to do"

The service runs fine under the "Local System" account.
 
M

Marc Gravell

Well, have you tried getting your service to tell you what is wrong?
perhaps catch some exceptions and log the real error to the event log?
It would also help to know what your service is attempting to do...
for instance, if it is trying to log onto a protected resource using
the NT identity, then note that it will be using the *computer*
identity (via "network service"), and not the identity of any user. If
you need protected access, one option is to run as a specific user.

Marc
 
S

sunil

Marc said:
Well, have you tried getting your service to tell you what is wrong?
perhaps catch some exceptions and log the real error to the event log?
It would also help to know what your service is attempting to do...
for instance, if it is trying to log onto a protected resource using
the NT identity, then note that it will be using the *computer*
identity (via "network service"), and not the identity of any user. If
you need protected access, one option is to run as a specific user.

Marc

Hi Marc,
I gave the exception handler. The exception caught is
InvalidOperationException if the service is installed in user's
Personal folder. If the service is installed in Program Files folder,
then the exception caught is TimeOutException.
I tried to start the service from the Service Controller Manager. The
behavior is the same.
Thanks for the response
 
M

Marc Gravell

You haven't really indicated what your service might be attempting to
do... if you are (as you suggest) successfully catching exceptions in
your managed code, then some clue as to what the exception handler
*surrounds* will probably tell you what isn't working...

Marc
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Hi Marc,
I gave the exception handler. The exception caught is
InvalidOperationException if the service is installed in user's
Personal folder.

Well this is pretty evidend, you are not installing it under an user account
but under network service.
If the service is installed in Program Files folder,
then the exception caught is TimeOutException.
I tried to start the service from the Service Controller Manager. The
behavior is the same.

Can you post some code? at least the code you use in the onStart method
 
S

sunil

Marc said:
You haven't really indicated what your service might be attempting to
do... if you are (as you suggest) successfully catching exceptions in
your managed code, then some clue as to what the exception handler
*surrounds* will probably tell you what isn't working...

Marc

Hi Marc,
In the onstart() method, I am trying to open a configuration file(XML
file) and then based on the content of the files, I initialize few
things. I am not accessing any other resource other than the
configuration file
May be, I can understand the reason for the failure in the case where I
installed the service in user's personal data folder(access denied is
being thrown).
But if the service is to be installed in program files folder, why is
it that the error is thrown
Thanks for the response
 
W

Willy Denoyette [MVP]

sunil said:
Hi Marc,
In the onstart() method, I am trying to open a configuration file(XML
file) and then based on the content of the files, I initialize few
things. I am not accessing any other resource other than the
configuration file
May be, I can understand the reason for the failure in the case where I
installed the service in user's personal data folder(access denied is
being thrown).
But if the service is to be installed in program files folder, why is
it that the error is thrown
Thanks for the response

OnStart has to start a "service thread" and return within 30 seconds. As far as I
understand, your service is not a service, actually it does nothing else than reading a file
and block or simply return from OnStart. When it blocks, the SCM will time-out, when it
returns whithout having a service thread running it will stop with this :
error:
"The <servicename> service on Local Computer started and then stopped.
Some services stop automatically if they have no work to do"

Willy.
 
S

sunil

Hi all,
thanks everybody for giving such valuable inputs.
I have noticed that, if I install the network service in ProgramFiles
folder, the application log entry showed:
Service cannot be started. System.UnauthorizedAccessException: Access
to the path 'C:\Program Files\MyService\error.txt' is denied.
Actually what I am doing is to write to a text file, that the
configuration file is loaded. If the text file is not there, I create
it. I think this is where the error occurs.
I tried to create the text file before installing the service, and gave
full control to Users group manually, then there is no problem at all.
The service started successfully.
Basing on this, how can I create a text file,if it does not exist, and
give write permissions to Users group from my program

Thanks once again for the help
 
W

Willy Denoyette [MVP]

sunil said:
Hi all,
thanks everybody for giving such valuable inputs.
I have noticed that, if I install the network service in ProgramFiles
folder, the application log entry showed:
Service cannot be started. System.UnauthorizedAccessException: Access
to the path 'C:\Program Files\MyService\error.txt' is denied.
Actually what I am doing is to write to a text file, that the
configuration file is loaded. If the text file is not there, I create
it. I think this is where the error occurs.
I tried to create the text file before installing the service, and gave
full control to Users group manually, then there is no problem at all.
The service started successfully.
Basing on this, how can I create a text file,if it does not exist, and
give write permissions to Users group from my program

Thanks once again for the help


The "local service" account has no write access privileges to the "program files" and it's
sub-dirs, so you'll have to grant Write access privileges for "local service" to 'C:\Program
Files\MyService before you can create files into this path.

Willy.
 
S

sunil

The "local service" account has no write access privileges to the "program files" and it's
sub-dirs, so you'll have to grant Write access privileges for "local service" to 'C:\Program
Files\MyService before you can create files into this path.

Willy.


Hi,
can you tell me how to do it? or may be direct me to some articles
which discuss it
thanks for the help
 
W

Willy Denoyette [MVP]

sunil said:
Hi,
can you tell me how to do it? or may be direct me to some articles
which discuss it
thanks for the help


The easiest is by running the cacls.exe command-line tool.
Running this:
cacls "C:\Program Files\MyService" /E /G "nt authority\network service:W"
will edit the ACE and add write perms. to network service to the folder "C:\Program
Files\MyService".

run help cacls to see all options.

Willy.
 
S

sunil

The easiest is by running the cacls.exe command-line tool.
Running this:
cacls "C:\Program Files\MyService" /E /G "nt authority\network service:W"
will edit the ACE and add write perms. to network service to the folder "C:\Program
Files\MyService".

run help cacls to see all options.

Willy.

Hi,
I tried that from my command-line, changed the access list and then
started my service. It worked great.
But since I do not know what will be the installation folder
beforehand, I have to change the access list from my program. How do I
do this? I have tried using:

Process myProcess = new Process();
myProcess.StartInfo.FileName = "cacls.exe";
myProcess.StartInfo.Arguments = @"C:\Program Files\MyService" + "/E /G"
+
@"nt
authority\network service:W";
myProcess.Start();
myProcess.WaitForExit();

But this doesn't seem to change the access list. please help me
thanks for the valuable time you have spent for me
 
S

sunil

The easiest is by running the cacls.exe command-line tool.
Running this:
cacls "C:\Program Files\MyService" /E /G "nt authority\network service:W"
will edit the ACE and add write perms. to network service to the folder "C:\Program
Files\MyService".

run help cacls to see all options.

Willy.

Hi,
I tried that from my command-line, changed the access list and then
started my service. It worked great.
But since I do not know what will be the installation folder
beforehand, I have to change the access list from my program. How do I
do this? I have tried using:

Process myProcess = new Process();
myProcess.StartInfo.FileName = "cacls.exe";
myProcess.StartInfo.Arguments = @"C:\Program Files\MyService" + "/E /G
"
+ @"nt authority\network service:W";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.Start();
EventLog.WriteEntry(sSource, myProcess.StandardOutput.ReadToEnd());
myProcess.WaitForExit();

There seems to be a problem. From my application log, I found out that
it is waiting for my reply.
The response written is:Are you sure(y/n)?
How can I send an answer as "y" from my program.
please help me
thanks for the valuable time you have spent for me
 
W

Willy Denoyette [MVP]

sunil said:
Hi,
I tried that from my command-line, changed the access list and then
started my service. It worked great.
But since I do not know what will be the installation folder
beforehand, I have to change the access list from my program. How do I
do this? I have tried using:

Process myProcess = new Process();
myProcess.StartInfo.FileName = "cacls.exe";
myProcess.StartInfo.Arguments = @"C:\Program Files\MyService" + "/E /G
"
+ @"nt authority\network service:W";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.Start();
EventLog.WriteEntry(sSource, myProcess.StandardOutput.ReadToEnd());
myProcess.WaitForExit();

There seems to be a problem. From my application log, I found out that
it is waiting for my reply.
The response written is:Are you sure(y/n)?
How can I send an answer as "y" from my program.
please help me
thanks for the valuable time you have spent for me


Well you could redirect stdin and send it a "y" followed by a return, but I hate this idea,
simply because you need a user to interpret the real question.
Much better is do it using the V2 System.Security.AccessControl namespace.
Following is how you could proceed.....

using System.Security.AccessControl;
....

string authority = "nt authority";
string account= "network service";
string path = @"c:\program files\...............";
string identity = String.Format(@"{0}\{1}",
authority , account);
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity ds = di.GetAccessControl(AccessControlSections.All);
FileSystemAccessRule fsaRule =
new FileSystemAccessRule(identity , FileSystemRights.Write,
AccessControlType.Allow);
ds.AddAccessRule(fsaRule);
di.SetAccessControl(ds);
....

Willy.
 
S

sunil

Well you could redirect stdin and send it a "y" followed by a return, but I hate this idea,
simply because you need a user to interpret the real question.
Much better is do it using the V2 System.Security.AccessControl namespace.
Following is how you could proceed.....

using System.Security.AccessControl;
...

string authority = "nt authority";
string account= "network service";
string path = @"c:\program files\...............";
string identity = String.Format(@"{0}\{1}",
authority , account);
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity ds = di.GetAccessControl(AccessControlSections.All);
FileSystemAccessRule fsaRule =
new FileSystemAccessRule(identity , FileSystemRights.Write,
AccessControlType.Allow);
ds.AddAccessRule(fsaRule);
di.SetAccessControl(ds);
...

Willy.

Hi,
I had tried out the second suggestion that you have made. It didn't
work out for me.The stack trace is:
Service cannot be started.
System.Security.AccessControl.PrivilegeNotHeldException: The process
does not possess the 'SeSecurityPrivilege' privilege which is required
for this operation.
at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType
resourceType, String name, SafeHandle handle, AccessControlSections
accessControlSections, RawSecurityDescriptor& resultSd)
at
System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType
resourceType, Boolean isContainer, String name, SafeHandle handle,
AccessControlSections includeSections, Boolean createByName,
ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean
isContainer, String name, AccessControlSections includeSections,
Boolean isDirectory)
at System.Security.AccessControl.DirectorySecurity..ctor(String
name, AccessControlSections includeSections)
at System.IO.DirectoryInfo.GetAccessControl(AccessControlSections
includeSections)


For the first suggestion that you have given, I had redirected the
standard input and passed a "y", but the service never entered
"running" state. It is always in StartPending state.
Also the eventlog entries are not being written properly(only the first
one is written)

Process myProcess = new Process();
string accountName = "\"nt authority\\network service\":F";
string argument = '"' +
Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName
+ '"' + @"/E" + @" /G " + accountName;
myProcess.StartInfo.FileName = "cacls";
myProcess.StartInfo.Arguments = argument;
EventLog.WriteEntry(sSource, argument);
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardError = true;

myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
EventLog.WriteEntry(sSource,
myProcess.StandardOutput.ReadToEnd());

myProcess.StandardInput.WriteLine("y");
EventLog.WriteEntry(sSource,
myProcess.StandardOutput.ReadToEnd());
EventLog.WriteEntry(sSource,
myProcess.StandardError.ReadToEnd());

myProcess.WaitForExit();

EventLog.WriteEntry(sSource,"Changed the Access Control
list");

service never seemed to have started successfully.
Thanks for all the help and valuable insights you have given me.
 
W

Willy Denoyette [MVP]

sunil said:
Hi,
I had tried out the second suggestion that you have made. It didn't
work out for me.The stack trace is:
Service cannot be started.
System.Security.AccessControl.PrivilegeNotHeldException: The process
does not possess the 'SeSecurityPrivilege' privilege which is required
for this operation.
at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType
resourceType, String name, SafeHandle handle, AccessControlSections
accessControlSections, RawSecurityDescriptor& resultSd)
at
System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType
resourceType, Boolean isContainer, String name, SafeHandle handle,
AccessControlSections includeSections, Boolean createByName,
ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean
isContainer, String name, AccessControlSections includeSections,
Boolean isDirectory)
at System.Security.AccessControl.DirectorySecurity..ctor(String
name, AccessControlSections includeSections)
at System.IO.DirectoryInfo.GetAccessControl(AccessControlSections
includeSections)


For the first suggestion that you have given, I had redirected the
standard input and passed a "y", but the service never entered
"running" state. It is always in StartPending state.
Also the eventlog entries are not being written properly(only the first
one is written)

Process myProcess = new Process();
string accountName = "\"nt authority\\network service\":F";
string argument = '"' +
Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName
+ '"' + @"/E" + @" /G " + accountName;
myProcess.StartInfo.FileName = "cacls";
myProcess.StartInfo.Arguments = argument;
EventLog.WriteEntry(sSource, argument);
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardError = true;

myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
EventLog.WriteEntry(sSource,
myProcess.StandardOutput.ReadToEnd());

myProcess.StandardInput.WriteLine("y");
EventLog.WriteEntry(sSource,
myProcess.StandardOutput.ReadToEnd());
EventLog.WriteEntry(sSource,
myProcess.StandardError.ReadToEnd());

myProcess.WaitForExit();

EventLog.WriteEntry(sSource,"Changed the Access Control
list");

service never seemed to have started successfully.
Thanks for all the help and valuable insights you have given me.



But you can't do this from your service, this is something that should be done from the
service "installer". Your service runs as a non privileged user 'network service" and you
try to execute commands only allowed by administrators. Services should NEVER EVER consider
having these privileges.

Willy.
 
S

sunil

But you can't do this from your service, this is something that should be done from the
service "installer". Your service runs as a non privileged user 'network service" and you
try to execute commands only allowed by administrators. Services should NEVER EVER consider
having these privileges.

Willy.

Hi,
Thank you for all the help. I have learned lot of things from these
conversations. I have made a huge progress.
I have added the following code to the ProjectInstaller.cs:

string authority = "nt authority";
string account = "network service";
string identity = String.Format(@"{0}\{1}", authority, account);

DirectoryInfo di = new DirectoryInfo(@"C:\Program Files\MyService");
DirectorySecurity ds = di.GetAccessControl(AccessControlSections.All);
FileSystemAccessRule fsaRule =
new FileSystemAccessRule(identity,
FileSystemRights.Write,

AccessControlType.Allow);
ds.AddAccessRule(fsaRule);
di.SetAccessControl(ds);

And it works now successfully.But I have a small question regarding the
path.
As you can see, the path that I gave(which is the default installation
folder) is complete path. But if the users installs the service at
different location, then I have a problem. I have to give permissions
to "that" folder. How do I do this?

One more question :Since only admins can change the security settings,
how do I specify that admin privileges are required to install the
application.
Thank you
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top