Answered by:
Accessing network drives

Question
-
I'm sorry, but can't find a better section to post this in. Please move to a more appropriate section if needed.
I have (written) a windows service that can either run as a service or as a console app (by passing a command line argument). The program runs on computer A and accesses a directory on computer B and a directory on computer C.
When I run the application version, the program works as expected and can access both remote directories. If I run the program as a service, it can only access the directory on computer B and I get a UnAuthorized Access exception for computer C.
I'm accessing the drive by IP address (e.g \\192.168.13.55\somefolder and 192.168.33.34\otherfolder) and the credentials for all computers are different. I can also access the directories using the above IP address from Windows Explorer.
The service runs with LocalSystem privilege and a valid username/password is specified on system A (Adminstrator credentials for computer A) for the service in the service manager.
To make matters worse, if I run the service version on another computer (Z), I can't access any of the remote directories while the console version again works happily as expected. Another service on this computer accessing one of those directories still works as expected.
I'm now trying to understand how credentials are used when remote directories are accessed. Can somebody point me to an article how it all works? If somebody has a solution based on the above information, it would also be appreciated ;-)
Thanks in advance.
Note:
I usually 'code' the service installer using the VisualStudio drag-n-drop functionality. This service differs in that I created it from scratch (read: copied it from somewhere on the web). The other difference with the other services that I have written is that this one attempts to access two different computers while the others only access a remote directory on one computer.
Just in case I did something wrong with the installer, the code (I did compare it to the designer file generated by VisualStudio 2012 for another service and did not find relevant differences).
using System; using System.ComponentModel; using System.Configuration.Install; using System.ServiceProcess; namespace WAC { [RunInstaller(true)] public class WACServiceInstaller : Installer { /// <summary> /// Public Constructor for WindowsServiceInstaller. /// - Put all of your Initialization code here. /// </summary> public WACServiceInstaller() { ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller(); ServiceInstaller serviceInstaller = new ServiceInstaller(); //# Service Account Information serviceProcessInstaller.Account = ServiceAccount.LocalSystem; serviceProcessInstaller.Username = null; serviceProcessInstaller.Password = null; //# Service Information serviceInstaller.DisplayName = "WAC"; serviceInstaller.Description = "Checks if scheduled assets are available"; serviceInstaller.StartType = ServiceStartMode.Manual; //# This must be identical to the WindowsService.ServiceBase name //# set in the constructor of WindowsService.cs serviceInstaller.ServiceName = "WAC Service"; this.Installers.Add(serviceProcessInstaller); this.Installers.Add(serviceInstaller); } } }
Note that some comments still exist from the original source.
- Edited by sterretje_K5 Wednesday, February 3, 2016 12:09 PM
Answers
-
If you are using the Network Service account then the connection will be made by the machine name (i.e. MyMachine$). Notice the $ on the end. If you do this through the UI then make sure you expand the object types to include computers. Then you can type in the computer name. When you look at the list of permissions you'll see the computer show up but it'll have a $ on the end to identify it as a computer. The UI will handle this for you. If you're doing this programmatically or via scripts then the $ is needed.
- Proposed as answer by Kristin Xie Monday, February 15, 2016 9:47 AM
- Marked as answer by Kristin Xie Wednesday, February 17, 2016 9:48 AM
All replies
-
I'm now trying to understand how credentials are used when remote directories are accessed. Can somebody point me to an article how it all works? If somebody has a solution based on the above information, it would also be appreciated ;-)
Local/Systems account has permissions to access resources on the local machine only. It's plain and simple.
The console application is using the permissions of the logged in user account logged into the machine. And if the logged in user account has permissions to access resources on remote machines, then the console application running under the context of the user account can access the resource.
If the Windows service needs the same kind of permissions, then it too must use an user account that has the permissions to access remote resources and not use the Local/Systems account limited to the machine's local resources only.
-
You didn't post the code you're using to access the file system. By default the credentials used will be the thread's principal. For a service it will be the account that the service is configured to run as. For a service to access network resources you need to either use Network Service or a domain account. If you use Network Service then the remote resource needs to allow connections from the machine as that is the account it will come across as. For a domain account it would simply be the account that you configured.
Caveats to using shared folders however. Shared folders have 2 levels of permissions. The first permission is the share itself. In order to read a share you need to make sure the appropriate account has at least read share permissions (configured when you set up the share). Once the share permissions are set then NTFS permissions kick in as normal.
Michael Taylor
http://blogs.msmvps.com/p3net
-
Sorry that the post possibly did not contain all the information; I was afraid that that would happen ;-)
On computers A and Z (where the services run), the same credentials are used for the console version and service version (Administrator, don't ask).
The one service can access computer B's directory (running as a service from both computer A and computer Z) and has this in the installer's designer file
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; this.serviceProcessInstaller1.Password = null; this.serviceProcessInstaller1.Username = null;
This exactly matches what I have in the new one that I copied 'from scratch' (posted above). So this leaves the question why this does work and the installer (?) of the new one gives me grey hair.
Example code that exhibits the problem; it uses Directory.GetFiles().
// test access to all directories for (int afcnt = 0; afcnt < Program.cfg.Assetfolders.Length; afcnt++) { try { string assetdirectory = Program.cfg.Assetfolders[afcnt].Directory; Logger.LogInformation(String.Format("Checking '{0}'", assetdirectory)); string[] filelist = Directory.GetFiles(assetdirectory); } catch (Exception ex) { Logger.LogDebug(ex); } for (int hfcnt = 0; hfcnt < Program.cfg.Assetfolders[afcnt].Hotfolders.Length; hfcnt++) { try { string directory = Program.cfg.Assetfolders[afcnt].Hotfolders[hfcnt].Directory; Logger.LogInformation(String.Format("Checking '{0}'", directory)); string[] filelist = Directory.GetFiles(directory); } catch (Exception ex) { Logger.LogDebug(ex); } } }
This is an overview of the situation
|computer B |computer C | ---------------+---------------+---------------+ computer A | | | ---------------+---------------+---------------+ console app 1 | OK | OK | ---------------+---------------+---------------+ service app 1 | FAIL | FAIL | ---------------+---------------+---------------+ console app 2 | OK | N/A | ---------------+---------------+---------------+ service app 2 } OK | N/A | ---------------+---------------+---------------+ computer Z | | | ---------------+---------------+---------------+ console app 1 | OK | OK | ---------------+---------------+---------------+ service app 1 | OK | FAIL | ---------------+---------------+---------------+ console app 2 | OK | N/A | ---------------+---------------+---------------+ service app 2 | OK | N/A | ---------------+---------------+---------------+
I will try the networkservice account and see if it makes a difference.
- Edited by sterretje_K5 Thursday, February 4, 2016 5:33 AM
-
OK, after changing to networkservice and reinstalling on both systems, what was working before for this new service no longer works (when running as a service).
With my limited understanding of the networking / sharing subject in Windows, it can make sense. I assume I have to make changes to the shared drives on computers B and C. Question is if I must allow NETWORK SERVICE access to those drives? Or something specific like computer A's name? Or something totally different?
Sorry, but I'm very illiterate when it comes to this type of stuff :-(
-
If you are using the Network Service account then the connection will be made by the machine name (i.e. MyMachine$). Notice the $ on the end. If you do this through the UI then make sure you expand the object types to include computers. Then you can type in the computer name. When you look at the list of permissions you'll see the computer show up but it'll have a $ on the end to identify it as a computer. The UI will handle this for you. If you're doing this programmatically or via scripts then the $ is needed.
- Proposed as answer by Kristin Xie Monday, February 15, 2016 9:47 AM
- Marked as answer by Kristin Xie Wednesday, February 17, 2016 9:48 AM