Map a Network Drive From Code for Cross-Domain File Copy

The other day, I had to copy a file from a Windows Service running on our Web server which is outside of our firewall, and not a trusted member of our domain, to a folder on a share inside of the firewall.  Should be easy, right?  Well, it turns out it that it’s a bit more complicated than I first thought.


In this case I had a username/password in the domain that I could use to access the share from the server.  I could successfully map the drive when logged into the console, but my service couldn’t see this mapped drive.  My service couldn’t impersonate this trusted domain user either (using LoginUser), since the server itself wasn’t a trusted member of the domain.


There’s no IO managed framework classes for connecting to a network share as a user, and there’s no way to connect to a network share, passing a domain\username and password, AFAIK.


I found out through a lot of searching that I needed to make a call to the WNetAddConnection APIs (mpr.dll) that would allow me to map a drive as a domain user in code.  I also have to run my service under the NETWORK_SERVICE account, so that it has access to network resources.


Luckily, I found an article on Code Project Map Network Drive (API) that does exactly this. So, my final solution (simplified), using the NetworkDrive class from the article looks like this:


     // Create a network mapped drive
     NetworkDrive drive = new NetworkDrive();

    
drive.ShareName = @”\\SOME_SERVER\SOME_SHARE”;
    
drive.LocalDrive = “I”;
    
drive.Force = true;
     drive.MapDrive(@”DOMAIN\USERNAME”, “password”);



     TextWriter textWriter = File.CreateText(@”I:\file.txt”);
    
textWriter.Write(“Some Text”);
    
textWriter.Close();
     drive.UnMapDrive();


This works really well.  The only problem may come up is that if the drive is mapped by some other application, forcing this mapping may cause problems. You could have some code that loops through drive letters until it finds one suitable.


-Brendan

About Brendan Tompkins

Brendan runs CodeBetter.Com and Devlicio.Us. He is a former MVP for Microsoft .NET and is president of Port Technology Services, a partner with Port Solution Integrators a provider of hardware and software integration services for the transportation and logistics industry.
This entry was posted in ASP.NET Tutorials, Most Popular. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • .netfighter

    I had the same issue  and suffered for 3 weeks, finally solved it through your post.thanks a lot

  • Malik Muhammad Iqbal

    Excellent post!!!!!!!!!!!!!!!!
    I have the same issue and solve it through your post.

    thanks alot

  • http://chvwovcm.com/ Fmjyentq

    D4cK3S

  • http://amit.ranjan.in@gmail.com amit

    Hey nick and Jas can i have the same aspx. I m also trying to do the same and facing some problem

  • nick

    thank you, thank you, thank you!!!

    this has been an annoyance for me for some time, so thanks for pointing me in the direction of such a helpful API :-) worked like a charm, first time, no messing around!! SUPERB!

  • Jas

    HI,
    Can you post complete working aspx page?

    Greatly apprciated!!!

    jask2002@yahoo.com

    Thanks
    Jas

  • Himadrish

    Is not there any simple way to do this? Using username, password…lots of thing…Just simple one way File.Copy() things…

    Say already there are some files in other machine, and that directory / server already map in my pc. No I would like to copy those one in my local drive….I think there must be some simple way to do this…

  • kau

    I am trying to do the same, Can you email me the code to this? My email address is kausmail@gmail.com. Thanks in advance…

  • http://golger.freeownhost.com Amir

    Can you send the source code of the classed you used?, it is not available on Code Project. please sent it to amirsabdou[at]y-a-h-o-o(dot)c/o/m
    Thanks

  • Ron Kegge

    Brendan,

    If you use the WNetUseConnection function, it will automagically pick an open drive letter to map. So, if another app has already mapped the drive to a particular drive letter, you could use this function. It returns the drive letter that was used (byref) so that you can subsequently write to the mapped drive.

  • Brendan Tompkins

    @, in C# allows you to, among other things, turn off character escaping in strings. YOu can do the same thing by escaping the backslashes. "\\\\SOMESERVER\\" instead of @"\\SOMESERVER\"

    You can set the run as account in the Services snap in, or in your service installer class within VS.NET when you build your component.

    Hope this helps.

  • Adam

    Two questions:

    1) "I also have to run my service under the NETWORK_SERVICE account" — How do you specify that?

    2) What is the "at" symbol (page errors when I type it in) in your code for?

    thanks,

    Adam

  • ben

    I’m trying to map a share that is on a 2k3 server to a w2k server that is running my asp.net app, and I can ping the 2k3 server, and I can browse to the share in windows explorer as well.

  • Brendan Tompkins

    Hmm. I didn’t try to connect to W2K, but you can see (ping) the server from the 2003 box by name, right?

  • ben

    Hi Brendan, I’m trying to do the same thing, but I keep getting a "The network name cannot be found", did you run into this issue at all? The server is running windows 2003 and I’m trying to connect from a windows 2000 box. thanks for your help!

    ben