Question

We are working on a web service that has to run a 3rd party process that interacts with a mapped network drive. So we have to map this drive programmatically from the web service.

I have already wrapped up WNetAddConnection2, etc. in a nicer class for another project, so I threw the code right in.

Our web service is running under UltiDev Cassini (instead of IIS) which runs under the System account. We get the error code for: "the specified device name is invalid" every time. I also tried impersonating other users in the web.config file, with the same results.

The drive will map just fine when I run my code from a console program under a normal user account.

I have also tried running the equivalent "net use" command from C# with the exact same results as WNetAddConnection.

Does anyone know why a windows service or System user wouldn't be able to map network drives?

Does anyone know a workaround? Simply mapping the drive on system startup would be a solution, but how could the system/impersonated user access it?

Link for UltiDev Cassini: UltiDev

SOLUTION: I set the UltiDev Cassini service to logon under Administrator and everything is working. The ASP .Net impersonation must not work as planned.

Was it helpful?

Solution

The LOCAL_SYSTEM account presents Anonymous credentials on the network. You could use a UNC network share to access this information, provided that anonymous (Everyone) has access to the share.

You can also install Cassini as a windows service which you could configure to run under a different user.

OTHER TIPS

If you're using the Local System account, then I believe it's inherently incapable of accessing network [foo]. I'd say impersonation is your only viable path. Technically you could reduce access controls on the share to the point that anyone could read/write to the share, but that brings more problems than solutions.

We had the same issue. The problem happens because of the account the code is running under. You can get around this as we did by using the following class. You have to map the drive in the same code you're using to access/copy files. The pattern we use is to always check t see if the drive is connected first. if so, we disconnect it, and then reconnect it. if not, we just connect it. It seems to clear up the issue you're describing.

public static class NetworkDrives
    {
        public static bool  MapDrive(string DriveLetter, string Path, string Username, string Password)
        {

            bool ReturnValue = false;

            if(System.IO.Directory.Exists(DriveLetter + ":\\"))
            {
                DisconnectDrive(DriveLetter);
            }
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;

            p.StartInfo.FileName = "net.exe";
            p.StartInfo.Arguments = " use " + DriveLetter + ": " + '"' + Path + '"' + " " + Password + " /user:" + Username;
            p.Start();
            p.WaitForExit();

            string ErrorMessage = p.StandardError.ReadToEnd();
            string OuputMessage = p.StandardOutput.ReadToEnd();
            if (ErrorMessage.Length > 0)
            {
                throw new Exception("Error:" + ErrorMessage);
            }
            else
            {
                ReturnValue = true;
            }
            return ReturnValue;
        }
        public static bool DisconnectDrive(string DriveLetter)
        {
            bool ReturnValue = false;
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;

            p.StartInfo.FileName = "net.exe";
            p.StartInfo.Arguments = " use " + DriveLetter + ": /DELETE";
            p.Start();
            p.WaitForExit();

            string ErrorMessage = p.StandardError.ReadToEnd();
            string OuputMessage = p.StandardOutput.ReadToEnd();
            if (ErrorMessage.Length > 0)
            {
                throw new Exception("Error:" + ErrorMessage);
            }
            else
            {
                ReturnValue = true;
            }
            return ReturnValue;
        }

    }

Instead of a mapped drive, could you connect using the UNC share?

I'd still impersonate a user that has access to the share.

I have actually done this before, but it was a VERY long time ago -- like 1997, and Win NT 3.51 with Delphi 2

I'm running from memory, but I think it goes something like this: You use the Win API:

WNetAddConnection2()

Info on the call: http://msdn.microsoft.com/en-us/library/aa385413(VS.85).aspx

You can get the c# signature from pInvoke.net: http://www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html

Note on configuration: I think that you will need to set up a domain account for the service, and run the service with the identity of that account instead of local system. I think that you pass null as the user name and password.

You might be able to run the service as local system pass the username and password of a domain account -- I don't know whether the system account is allowed any network access at all.

The general concept to keep in mind is that 'mapped drive letters' are a User concept, not a System concept. So when Joe logs in to the Windows Computer, the mapped drives are attached to the Joe user account. When a Windows Service is running, generally it's running under the LOCAL_SYSTEM 'user account', meaning that LOCAL_SYSTEM does not know about Joe's mapped drive letters.

Therefore, UNC access to network shares are the way to go when trying to access any remote resource from within a Windows Service. Note that you could run the Windows Service under the context of the 'Joe' user account, or you could create a dummy AD account called something like 'MyServiceAccount' and give that account rights to the UNC, or you could use Impersonation and have the Windows Service log in to the local workstation using the NetLogon() function with an impersonation handle and then access the UNC from there.

There are lots of ways to do it, but the all come down to User accounts are associated with Mapped Drives and UNC access.

Good Luck, hope this information helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top