Challenge:
- Access files located in the network shared folder.
- Shared folder is restricted to specific users only.
- Last but not least, do all the above programatically using C#.Net.
Solution:
Achieved it by using the below judiciously
[DllImport(“mpr.dll”)]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
[DllImport(“mpr.dll”)]
private static extern int WNetCancelConnection2(string name, int flags,
bool force);
First, Create the class to make the connection to the networkshare as below.
public class NetworkConnection : IDisposable { string _networkName; public NetworkConnection(string networkName, NetworkCredential credentials) { _networkName = networkName; var netResource = new NetResource() { Scope = ResourceScope.GlobalNetwork, ResourceType = ResourceType.Disk, DisplayType = ResourceDisplaytype.Share, RemoteName = networkName }; var result = WNetAddConnection2( netResource, credentials.Password, credentials.UserName, 0); if (result != 0) { throw new Win32Exception(result, "Error connecting to remote share"); } } ~NetworkConnection() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { WNetCancelConnection2(_networkName, 0, true); } [DllImport("mpr.dll")] private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags); [DllImport("mpr.dll")] private static extern int WNetCancelConnection2(string name, int flags, bool force); } [StructLayout(LayoutKind.Sequential)] public class NetResource { public ResourceScope Scope; public ResourceType ResourceType; public ResourceDisplaytype DisplayType; public int Usage; public string LocalName; public string RemoteName; public string Comment; public string Provider; } public enum ResourceScope : int { Connected = 1, GlobalNetwork, Remembered, Recent, Context }; public enum ResourceType : int { Any = 0, Disk = 1, Print = 2, Reserved = 8, } public enum ResourceDisplaytype : int { Generic = 0x0, Domain = 0x01, Server = 0x02, Share = 0x03, File = 0x04, Group = 0x05, Network = 0x06, Root = 0x07, Shareadmin = 0x08, Directory = 0x09, Tree = 0x0a, Ndscontainer = 0x0b }
Second, Access the file using the above class as below
[TestMethod] public void TestConnectivity_Using_Credentials() { try { System.Net.NetworkCredential readCredentials = new NetworkCredential(@"Domain\UserName", "Password"); string filepath = @"\\Servername\DevTest\MyFiles"; using (new NetworkConnection(filepath, readCredentials)) { File.Copy(@"\\Servername\DevTest\MyFiles\XXX.txt", @"\\Servername\DevTest\MyFiles\XXX-Copy.txt"); } Assert.AreEqual<string>("01", "01", "Success"); } catch { Assert.Fail(); } }
Errors encountered
When i used the WNetAddConnection2 method, it returned 1219 as result code. Well, it worked for my own credentials, but when i passed the service credentials to access the files. I was facing this problem.
After querying uncle Google, I realized that the natively windows allows only one user to be used to map the network drive, i.e, i cannot use my own credentials and service credentials (both being different) to access the same network share from the same server concurrently.
As as alternative, i use the ip Address to access the networkshare using my service account. and Violla, it worked like a charm.
Links referred to develop:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa385413(v=vs.85).aspx
Links referred to troubleshoot
http://stackoverflow.com/questions/6207289/wnetaddconnection2-returns-1219
http://social.msdn.microsoft.com/Forums/sv/wsk/thread/f43c2faf-3df3-4f11-9f5e-1a9101753f93
http://forums.asp.net/t/1788841.aspx/1
Adios.