4

I have a windows service which polls for a specific folder for creation of new files. This works fine when the folder is in one of the local drives such as C: or D: The service fails to find a folder on a mapped drive.

Here is the code which does the checking for folder exist before polling:

System.Security.Principal.WindowsIdentity userIdentity =
            System.Security.Principal.WindowsIdentity.GetCurrent();
            System.Security.Principal.WindowsPrincipal principal =
                new System.Security.Principal.WindowsPrincipal(userIdentity);

            MappedDriveResolver mdr = new MappedDriveResolver();
            if (mdr.isNetworkDrive(folderPath))
            {
                LoggingAppWrapper.LogDeveloperMessage(folderPath + " is on a Mapped    drive", 1, TraceEventType.Information, string.Empty);

            }

MappedDriveResolver is a class that I found hereHow do I determine a mapped drive's actual path?

The code in that link works fine from a simple console application, but fails when it is part of windows service. Any suggestions as to what has to be done for the code to work for a windows service?

Regards.

Community
  • 1
  • 1
Codehelp
  • 2,919
  • 6
  • 48
  • 85
  • You're certain that the account the service is executing within has the appropriate permissions? – kpcrash Mar 29 '12 at 12:46
  • I think this answer will help you: [Answer for thread "Map a network drive to be used by a service"][1] [1]: http://stackoverflow.com/a/4763324/3860297 – sekerg Oct 19 '14 at 12:10

1 Answers1

4

I would recommend you configure your service to use UNC paths for folders not on the server running the service.

Mapped drives are a usability feature for users and as such they are specific to that users profile/environment. Meaning, when you login you may have a drive X: that is mapped to \\server1\share1 but when I login my drive X: could be mapped to \\server2\share2 instead. The actual mapping process is either saved as part of your profile with the "Reconnect at logon" or is handled by a logon script.

You need to check what account the service is running under and make sure that mapped drive exists for that user environment (This might help How to map a network drive to be used by a service).

Edit:

The reason your console application works and the service doesn't is because of the differences between the environment they are running in.

To illustrate this, take this console application, compile it and then run it as a Schedule Task. Set the "path" variable to be a mapped drive that your user can access.

    static void Main(string[] args) {
        MappedDriveResolver mdr = new MappedDriveResolver();
        string logfile;
        string path = @"I:\";
        string[] files;

        // Write out "log" file to where this is running from
        logfile = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
        logfile = Path.Combine(logfile, "log.txt");

        using (StreamWriter sw = new StreamWriter(logfile, true)) {

            try {
                sw.WriteLine("Checking path " + path);
                if (mdr.isNetworkDrive(path)) {
                    sw.WriteLine("Network Drive: Yes");
                } else {
                    sw.WriteLine("Network Drive: No");
                }
            } catch (Exception ex) {
                sw.WriteLine("Exception: " + ex.Message);
            }

            try {
                sw.WriteLine("Resolve path " + path);
                string newpath = mdr.ResolveToUNC(path);
                sw.WriteLine("Resolved path " + newpath);
            } catch (Exception ex) {
                sw.WriteLine("Exception: " + ex.Message);
            }

            try {
                sw.WriteLine("Get file list from " + path);
                files = Directory.GetFiles(path);
                if (files == null || files.Length == 0) {
                    sw.WriteLine("No files found");
                } else {
                    sw.WriteLine(string.Format("Found {0} files.", files.Length));
                }
            } catch (Exception ex) {
                sw.WriteLine("Exception: " + ex.Message);
            }

            sw.Flush();
            sw.Close();
        }
    }

Note: This is with the Windows 7 Task Scheduler

Test 1: Just run the app by double-clicking on it.
Result: Success

Test 2: Configure scheduled task to run as your user account with "Run only when user is logged on"
Result: Success

Test 3: Configure scheduled task to run as your user account with "Run whether user is logged on or not"
Result: Exceptions

Test 4: Configure schedule task to run as "Local Service" account.
Result: Exceptions

Test 1 & 2 work because they are using the currently logged in user environment including the mapped drives that are part of it.

Test 3 & 4 fail because they have their own user environment created for them, which does not have any mapped drives configured. It escapes me at the moment what the differences there are, but an "interactive" and "non-interactive" environment are different in some significant ways.

Community
  • 1
  • 1
Vermis
  • 2,180
  • 2
  • 15
  • 13
  • Ok ... I get that ... but why does the code work from a Console App but not from a Service? – Codehelp Apr 02 '12 at 05:48
  • I found some good information here [http://stackoverflow.com/questions/4396634/how-can-i-determine-if-a-given-drive-letter-is-a-local-mapped-usb-drive] ... again this works fine from a console app but fails through a Service!!! – Codehelp Apr 02 '12 at 06:58
  • @Codehelp Added a hopefully better explanation and a way to test it. – Vermis Apr 02 '12 at 19:58