3

I am trying to access a network file share with .NET Core. I have seen this solution for Net Standard:

How to provide user name and password when connecting to a network share

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 userName = string.IsNullOrEmpty(credentials.Domain)
            ? credentials.UserName
            : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);

        var result = WNetAddConnection2(
            netResource, 
            credentials.Password,
            userName,
            0);

        if (result != 0)
        {
            throw new Win32Exception(result);
        }   
    }

    ~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
    }

I have read that using [DllImport("mpr.dll")] in core is not advised. Is there a .net core way to do this.

Robert
  • 4,306
  • 11
  • 45
  • 95
  • Take a look at this one https://stackoverflow.com/questions/3700871/connect-to-network-drive-with-user-name-and-password/22378883 and look for the answer that says "Very elegant solution inspired from this one. This one uses only .Net library and does not need to use any command line or Win32 API." – Edney Holder May 09 '19 at 18:20

1 Answers1

11

Check out: https://www.nuget.org/packages/SimpleImpersonation/

Using that you can access a file share with a simple :

var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
    return System.IO.Directory.GetFiles( @"\\server\share" );
}); 
j0ffe
  • 621
  • 8
  • 13
  • 1
    Which kind of logonType would be appropriate for access to a share? – grek40 Jul 29 '19 at 08:44
  • @grek40, depends on the use case. They are explained here: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera - but when impersonating a user, do "what the user would do", and for that purpose I would use INTERACTIVE. – j0ffe Aug 19 '19 at 18:28
  • 1
    I used `LogonType.NewCredentials` for QNAP file network sharing – nieTenKoziol Jan 23 '20 at 05:54
  • 3
    This is a Windows only solution, does not work on linux or mac. – justin.m.chase Feb 01 '21 at 14:47
  • I get the error of System.ArgumentException: 'Username cannot contain \ or @ characters when domain is provided separately. (Parameter 'username')'. I have to include \ in he username so how to solve this issue.Below is my code: UserCredentials credentials = new UserCredentials("111.222.333.45", "ABC\Test.test", "Test@12"); @j0ffe – Sabbu Mar 23 '22 at 19:13