Brief Summary

I've written a Windows Service. It uses Process.Start() to launch a Console Application. The console application performs a File.Copy(), to copy a file from the local file system to a network share.

Problem: The file copy fails. I get an exception that tells me "part of the path could not be found".

When I run the Console Application directly, I don't get the error.

My Guess: I'm guessing that services, and processes spawned by services, do not have permissions to access non-local resources, including network shares.

My Attempted Fix: Run the service under a different user account. It didn't work.

Details

This is for a large transactional processing job. There is a dedicated server that periodically receives (through web services) thousands upon thousands of "transactions". These take the form of individual files, organized into a 5-level hierarchy. Each level has a folder, so the folder structure might be:

C:\OUTPUT\LEVEL_A\LEVEL_B\LEVEL_C\LEVEL_D\files

The "files" represent the individual transations. When a particular "LEVEL_D" is complete, a log file is created.

It can take DAYS to generate all the files. Currently, when the process is complete, someone manually organizes and processes the transations. Yuck.

My Windows Service implements a FileWatcher to look for the creation of the "log" files. When a log file is created, that means there is a "batch" of transactions that can be processed. When a log file is completed, I use System.Diagnostics.Process.Start() to launch a Console Application.

The Console Application contains no User Interface. All it does, really, is file i/o. One of the final steps is to take a newly created file (a pre-processed, concatenation of a transaction "batch") and copy it to another server for final production. It's this step that fails.

Is there no brave soul willing to take a stab at this? Let me re-hash it in case the above isn't clear.

I get the following error:

An unhandled exception of type 'System.IO.DirectoryNotFoundException' occurred in mscorlib.dll

Additional information: Could not find a part of the path "z:\".

The code that causes the error (I'm using the "PHP" tags, but this is C# code, of course):

if (!Directory.Exists(sack_destination + tape_name))
{
  Directory.CreateDirectory(sack_destination + tape_name);
}

"sack_destination" is a string that equates to "z:\mer". This is a mapped drive, a network share.

The code is contained in a Console Application, which is launched from a Windows Service application using System.Diagnostics.Process.Start.

I have tried running the service under the LocalSystem account, and as a local user account with Administrative + "run as service" privileges. The same error in each case.

I also tried running the service under NetworkResource account, but the service failed to start, with no specific error message, so I'm not sure what the problem is there.

The error does NOT occur when I manually run or debug the Console application.

What privileges are needed in order for an application spawned by a service to access network resources? Can those privileges be granted programmatically? In other words, can the service launch the process with specific credentials? If so, how (code snippet)?

Following my pattern in the C# forum, I'll answer my own question.

The issue is that the LocalSystem account, which most services run under by default, runs in it's own context. Thus, it doesn't have access to USER drive mappings.

Or, as a very obscure and unenlightening MSDN Article puts it:

A service that runs under a LocalSystem account or under a local user account can only access mapped drives that the service creates. Mapped drives are stored for each logon session. If a service runs under a LocalSystem account or under a local user account that does not create certain mapped drives, the service cannot access these mapped drives. Additionally, a service that runs under a local user account that creates certain mapped drives also receives a new set of mapped drives if you log off and then you log on again as the same local user.

The article then goes on to display massive code listings as a "work-around". Ignore all of that. The two relevant pieces of information are that you cannot use DRIVE MAPPINGS.

You can, however, use UNC Paths:

\\COMPUTER_NAME\SharedFolder\

The second clue is that the account used by the service, and thus by extension all processes it spawns, must have rights to the share. A "LocalSystem" account on a specific machine has no such rights. So, the service must run under a "User Account".

That's an inconvenience, to be sure, but can be handled by good installation documentation. In my case, my service application will be installed on the production machine by yours truly, so I can manually change the service Log On to a local user account.

When you use the Services applet in the Control Panel to do this, it will automatically add the requisite "Run as a service" privilege to that account.

Problem solved!

so if the services are running under the administrator of that particular machine and some user of any domain maps a netwrok drive on that machine. Will the services be able to get those netwrok mapped drives?

No, not a mapped drive by drive letter, only by UNC path. And the drive permissions will have to be assigned to the Administrator, rather than to "some user of the domain". At least, that was my experience.

No, not a mapped drive by drive letter, only by UNC path. And the drive permissions will have to be assigned to the Administrator, rather than to "some user of the domain". At least, that was my experience.

This helped me 2 years down the road. It helps speaking to yourself!:eek:

Glad I could help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.