.NET Core 中,可以使用 SharpCifs 库来访问和操作 Windows SMB 共享目录。SharpCifs 是一个基于 JCIFS 的 C# 实现,用于与 SMB 共享进行交互。本文主要介绍.NET Core中,使用SharpCifs访问windows共享目录或smb协义共享目录,或操作共享文件的方法代码。

1、SharpCifs的安装引用

使用Nuget管理工具搜索"SharpCifs"=>找到选择 "安装"

相关文档VS(Visual Studio)中Nuget的使用

代码地址https://github.com/zinkpad/SharpCifs

2、获取共享目录中路径和文件的方法

对于大量文件操作,可以考虑使用异步方式或批量操作来提高性能。确保应用程序具有访问 SMB 共享的权限。

//using System;
//using SharpCifs.Smb;
//获取文件夹的SmbFile-Object
var folder = new SmbFile("smb://UserName:Password@ServerIP/ShareName/FolderName/");
//UnixTime
var epocDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
//列出 items
foreach (SmbFile item in folder.ListFiles())
{
    var lastModDate = epocDate.AddMilliseconds(item.LastModified())
                                .ToLocalTime();
    var name = item.GetName();
    var type = item.IsDirectory() ? "dir" : "file";
    var date = lastModDate.ToString("yyyy-MM-dd HH:mm:ss");
    var msg = $"{name} ({type}) - LastMod: {date}";
    Console.WriteLine(msg);
}

3、连接共享目录和验证帐户密码

将用户名和密码硬编码在代码中是不安全的。建议使用配置文件或环境变量来存储凭据。确保 SMB 服务器的安全性,例如启用 SMB 签名和数据加密。大文件传输时,考虑使用缓冲区来提高性能。

//using System;
//using SharpCifs.Smb;
//设置本地udp广播端口。
//连接时使用主机名,
//将默认本地端口(137)更改为大于1024的值。
//在许多情况下,使用这个著名的港口是受到限制的。
//
// **如果可能,使用IP地址而不是主机名
// **获得更好的性能。
//
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
//string to Auth-Object.
var auth1 = new NtlmPasswordAuthentication("UserName:Password");
var smb1 = new SmbFile("smb://192.168.0.1/ShareName/FolderName/", auth1);
Console.WriteLine($"exists? {smb1.Exists()}");
//3 string to Auth-Object.
var auth2 = new NtlmPasswordAuthentication(null, "UserName", "Password");
var smb2 = new SmbFile("smb://HostName/ShareName/FolderName/", auth2);
Console.WriteLine($"exists? {smb2.Exists()}");
//插入用户密码到URL中.
var smb3 = new SmbFile("smb://UserName:Password@HostName/ShareName/FolderName/");
Console.WriteLine($"exists? {smb3.Exists()}");
//您可以将身份验证信息存储在SharpCifs.Std中。
SharpCifs.Config.SetProperty("jcifs.smb.client.username", "UserName");
SharpCifs.Config.SetProperty("jcifs.smb.client.password", "Password");
var smb4 = new SmbFile("smb://HostName/ShareName/FolderName/");
Console.WriteLine($"exists? {smb4.Exists()}");

4、从共享目录中读取文件

确保共享路径正确,提供正确的域名、用户名和密码。添加异常处理来捕获潜在的错误,例如网络连接失败、权限不足等。

//using System;
//using System.IO;
//using System.Text;
//using SharpCifs.Smb;
//获取目录的SmbFile.
var file = new SmbFile("smb://UserName:Password@ServerIP/ShareName/Folder/FileName.txt");
//获取可读的流。
var readStream = file.GetInputStream();
//创建读取缓存
var memStream = new MemoryStream();
//获取 bytes.
((Stream)readStream).CopyTo(memStream);
//Dispose可读的流。
readStream.Dispose();
Console.WriteLine(Encoding.UTF8.GetString(memStream.ToArray()));

5、在共享目录中创建新文件

确保账户在共享目录上具有足够的写入权限,文件路径应该相对于共享目录的根目录。对于大量文件操作,可以考虑使用异步方式或批量操作来提高性能。

//using System.Text;
//using SharpCifs.Smb;
//获取指定要创建的文件名的SmbFile。
var file = new SmbFile("smb://UserName:Password@ServerIP/ShareName/Folder/NewFileName.txt");
//创建文件
file.CreateNewFile();
//获取可写的stream.
var writeStream = file.GetOutputStream();
//写入 bytes内容.
writeStream.Write(Encoding.UTF8.GetBytes("Hello!"));
//Dispose 可写的 stream.
writeStream.Dispose();

6、浏览在局域网中的共享服务

用户需要有足够的权限访问共享目录,对于网络错误或文件操作异常,应进行适当的异常处理。设置本地udp广播端口。连接时使用主机名,将默认本地端口(8137)更改为大于1024的值。在许多情况下,使用这个端口是受到限制的。如果可能,使用IP地址而不是主机名,会有获得更好的性能。

//using System;
//using SharpCifs.Smb;
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
//得到本地的工作组
var lan = new SmbFile("smb://", "");
var workgroups = lan.ListFiles();
foreach (var workgroup in workgroups)
{
    Console.WriteLine($"Workgroup Name = {workgroup.GetName()}");
    try
    {
        //Get servers in workgroup.
        var servers = workgroup.ListFiles();
        foreach (var server in servers)
        {
            Console.WriteLine($"{workgroup.GetName()} - Server Name = {server.GetName()}");
            try
            {
                //Get shared folders in server.
                var shares = server.ListFiles();
                foreach (var share in shares)
                {
                    Console.WriteLine($"{workgroup.GetName()}{server.GetName()} - Share Name = {share.GetName()}");
                }
            }
            catch (Exception)
            {
                Console.WriteLine($"{workgroup.GetName()}{server.GetName()} - Access Denied");
            }
        }
    }
    catch (Exception)
    {
        Console.WriteLine($"{workgroup.GetName()} - Access Denied");
    }
}

7、主机名称解析

确保防火墙允许 SMB 访问,确保提供的用户名和密码具有正确的权限。

//using System;
//using System.Net;
//using SharpCifs.Netbios;
//设置本地udp广播端口。
//连接时使用主机名,
//将默认本地端口(137)更改为大于1024的值。
//在许多情况下,使用这个著名的港口是受到限制的。
//
// **如果可能,使用IP地址而不是主机名
// **获得更好的性能。
//
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
var naddr = NbtAddress.GetByName("HostName");
IPAddress addr = naddr.GetInetAddress();
Console.WriteLine($"IP = {addr}");

8、设置共享参数 

SharpCifs 提供了丰富的配置选项,可以根据需要进行调整,如超时设置、代理设置等。

//设置本地IP地址。
//如果发生连接错误(例如:连接失败:[NET BIOS NAME]),
//尝试设置本地IP地址。
//当设备的主机名作为DNS名称无效时,
//要确定当地的地址可能是不可能的。
SharpCifs.Config.SetProperty("jcifs.smb.client.laddr", "192.168.0.2");
//设置本地udp广播端口。
//连接时使用主机名,
//将默认本地端口(137)更改为大于1024的值。
//在许多情况下,使用这个著名的港口是受到限制的。
//
// **如果可能,使用IP地址而不是主机名
// **获得更好的性能。
//
SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8137");
//您可以将身份验证信息存储在SharpCifs.Std中。
SharpCifs.Config.SetProperty("jcifs.smb.client.username", "UserName");
SharpCifs.Config.SetProperty("jcifs.smb.client.password", "Password");
//如果您不使用DFS(分布式文件系统),
//禁用DFS可以提高NetBios名称解析的速度。
SharpCifs.Config.SetProperty("jcifs.smb.client.dfs.disabled", "true");
//更多的配置参数在JCIFS官方站点中。
//https://jcifs.samba.org/src/docs/api/overview-summary.html

9、刷新设置和连接缓存

使用 SMB 协议访问共享文件夹时,本地操作系统通常会缓存文件和目录信息,以提高访问速度。但是,缓存也可能导致数据不一致的问题,尤其是在文件频繁更新的情况下。操作系统会缓存 SMB 连接信息,以便下次访问时可以快速建立连接。

//----------------------------------------
//必选:版本0.2.9或更高。
//----------------------------------------
//
//强制应用设置值。
//在默认操作上,应用第一次smb处理时的设置值,并且不能更改。
//该方法强制应用SMB处理后更改的设置值。
//
//并且,这个方法处理当前无效的缓存连接。
//例如,在连接后30分钟内不能工作的连接将被处理。
SmbFile.Initialize();
//重置无效的连接。
//使用此方法处理无效连接,而无需操作设置值。
SmbTransport.ClearCachedConnections();
//重置所有(包括活动)连接。
//使用此方法处理所有连接,包括当前连接。
//注意,即使在数据传输期间,它也会处理连接。
SmbTransport.ClearCachedConnections(true);

推荐文档