WNetAddConnection2如何确定协议名称(SMB / CIFS,NFS)和版本

如何确定Windows上已安装的网络驱动器的协议名称(SMB / CIFS,NFS)和版本?
使用WNetAddConnection2连接共享文件夹,安全要求需要使用SMBv3协议,如何实现?怎么确定连接使用的什么协议?看参数没有设置协议的地方?

WNetGetNetworkInformation函数可以返回网络协议信息吗,该如何如使用?
C#代码如何实现?

1.打开“控制面板”->“程序和功能”,找到“Windows 功能”选项,展开“SMB 1.0/CIFS 文件共享支持”、“SMB 直接主机”和“SMB 1.0/CIFS 自动装载”等选项,查看是否已勾选,如果勾选则表示已安装相应协议版本。
2.打开“命令提示符”,输入“sc query rdr”,查看“TYPE”一栏中的值,如果为“FILE_SYSTEM_DRIVER”,则表示已安装“Redirected Drive Buffering SubSystem”(RDBSS)驱动,该驱动支持SMB协议。
3.打开“注册表编辑器”,找到“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters”键,查看“SMB1”和“SMB2”值,如果值为“1”,则表示已启用相应的SMB协议版本。关于使用WNetAddConnection2连接共享文件夹,安全要求需要使用SMBv3协议的问题,可以通过设置连接选项来实现。具体方法如下:
创建一个NETRESOURCE结构体,设置相应的参数,如远程共享文件夹路径、用户名和密码等。
创建一个CONNECTDLGSTRUCT结构体,设置相应的连接选项,如SMB版本为3.0、加密等级为AES128-CCM等。
调用WNetAddConnection2函数,将NETRESOURCE和CONNECTDLGSTRUCT结构体作为参数传入,即可建立使用SMBv3协议的共享文件夹连接。
4.关于如何确定连接使用的是什么协议,可以通过以下方法:
打开“命令提示符”,输入“net use”,查看已建立的连接列表,如果连接使用的是SMBv3协议,则在“类型”一栏中会显示“Microsoft Windows Network”。
打开“资源监视器”,找到“网络”选项卡,查看“协议”一栏中的值,如果为“SMB 3.X”,则表示连接使用的是SMBv3协议。如果为“NFS”,则表示连接使用的是NFS协议。
5.关于WNetGetNetworkInformation函数可以返回网络协议信息的问题,该函数可以返回与网络相关的信息,如计算机名、域名、网络连接状态等,但不能返回网络协议信息。如果需要获取网络协议信息,可以使用其他方法,如上述方法中的“命令提示符”和“资源监视器”。

CIFS NFS SMB Samba 文件共享协议 介绍

可以借鉴下
https://blog.csdn.net/whatday/article/details/123932194

要确定 Windows 上已安装的网络驱动器的协议名称和版本,可以使用 WNetAddConnection2 函数。该函数的第二个参数是一个网络连接对象,可以使用 WNetGetConnectionObject 函数获取。

在这个网络连接对象中,可以设置协议名称和版本。例如,要使用 SMBv3 协议连接共享文件夹,可以使用以下代码:

using System;  
using System.Net;  
using System.Net.Security;  
using System.Security.Authentication;  
using System.Security.Cryptography.X509Certificates;

namespace WNetAddConnection2Test  
{
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // 创建 SMB 协议连接对象  
            NetworkConnection netConnection = new NetworkConnection();  
            netConnection.Type = NetworkConnectionType.SMB;

            // 设置 SMB 协议版本为 3.0  
            netConnection.SMBVersion = SMBVersion.SMB3;

            // 连接共享文件夹  
            using (SMBClient client = new SMBClient())  
            {  
                client.Connect("localhost", 445);

                // 发送 SMB 请求,获取共享文件夹列表  
                SMBRequest request = new SMBRequest(SMBCommand.ListDirectory);  
                request.Connection = netConnection;  
                client.SendRequest(request);

                // 读取共享文件夹列表  
                SMBResponse response = new SMBResponse();  
                client.ReceiveResponse(response);  
                string[] directories = response.Directories;

                // 断开连接  
                client.Disconnect();  
            }  
        }  
    }  
}


在上面的代码中,我们创建了一个 SMB 协议连接对象,并将其 SMB 版本设置为 SMB3.0。然后,我们使用 SMBClient 类连接到 localhost 的 445 端口,并发送 SMB 请求以获取共享文件夹列表。SMB 请求中需要包含一个网络连接对象,我们可以通过 WNetGetConnectionObject 函数获取。

要使用 WNetAddConnection2 函数连接共享文件夹,可以使用以下代码:

using System;  
using System.Net;  
using System.Net.Security;  
using System.Security.Authentication;  
using System.Security.Cryptography.X509Certificates;

namespace WNetAddConnection2Test  
{
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // 创建网络连接对象  
            NetworkConnection netConnection = new NetworkConnection();  
            netConnection.Type = NetworkConnectionType.CIFS;

            // 设置 CIFS 协议版本为 2.0  
            netConnection.CIFSVersion = CIFSVersion.CIFS2;

            // 连接共享文件夹  
            using (FileSystemConnection fileSystemConnection = new FileSystemConnection())  
            {  
                fileSystemConnection.AddConnection(netConnection);

                // 连接共享文件夹  
                using (ShareAccessConnection shareAccessConnection = new ShareAccessConnection(fileSystemConnection))  
                {  
                    // 读取共享文件夹中的文件  
                    using (StreamReader reader = new StreamReader("test.txt"))  
                    {  
                        string line;  
                        while ((line = reader.ReadLine()) != null)  
                        {  
                            Console.WriteLine(line);  
                        }  
                    }  
                }  
            }  
        }  
    }  
}


在上面的代码中,我们创建了一个 CIFS 协议连接对象,并将其 CIFS 版本设置为 CIFS2.0。然后,我们使用 FileSystemConnection 类连接到共享文件夹,并使用 ShareAccessConnection 类连接共享文件夹。

要使用 WNetAddConnection2 函数连接共享文件夹,可以使用以下代码:

using System;  
using System.Net;  
using System.Net.Security;  
using System.Security.Authentication;  
using System.Security.Cryptography.X509Certificates;

namespace WNetAddConnection2Test  
{
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // 创建网络连接对象  
            NetworkConnection netConnection = new NetworkConnection();  
            netConnection.Type = NetworkConnectionType.NFS;

            // 设置 NFS 协议版本为 2.0  
            netConnection.NFSVersion = NFSVersion.NFS2;

            // 连接共享文件夹  
            using (NetworkConnection netConnection2 = new NetworkConnection())  
            {  
                netConnection2.Type = NetworkConnectionType.NFS;  
                netConnection2.NFSVersion = NFSVersion.NFS2;

                using (NFSClient client = new NFSClient())  
                


该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
在Windows上连接共享文件夹时,WNetAddConnection2函数可以用于建立网络连接,但是它并没有提供直接指定连接使用的协议的选项。默认情况下,Windows会尝试使用最新版本的支持的协议进行连接,例如SMBv3。

如果需要强制指定连接使用的协议,可以在连接共享文件夹的路径前加上协议名称,例如:

\\server\share

其中,如果使用的是SMB协议,则为:

\\server\share

如果使用的是NFS协议,则为:

\\server\share

关于如何确定已安装的网络驱动器的协议名称和版本,可以通过以下步骤:

  1. 打开“计算机管理”窗口,选择“设备管理器”。

  2. 展开“网络适配器”节点,找到网络驱动器。

  3. 右键单击网络驱动器,选择“属性”。

  4. 在“属性”窗口中,选择“驱动程序”选项卡,可以查看驱动程序的版本信息。

  5. 如果需要确定该驱动程序支持的协议名称和版本,可以在驱动程序的官方文档或厂商网站上查找相关信息。

关于WNetGetNetworkInformation函数,它可以用于获取网络连接的信息,包括连接所使用的协议名称和版本,但是该函数的返回值为NETINFOSTRUCT结构体,其中并没有直接提供协议名称和版本的信息。如果需要获取这些信息,需要对返回的NETINFOSTRUCT结构体进行解析和处理。具体可以参考MSDN文档中的示例代码。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

来自NewBing和LP的编写:

在Windows系统中,识别网络驱动器使用的协议(例如SMB、CIFS或NFS)以及版本通常比较困难,因为Windows并没有提供直接的API或者工具来获取这些信息。然而,你可以通过一些间接的方式去判断,例如检查网络流量或者查看服务器的配置。

对于使用WNetAddConnection2来连接共享文件夹的情况,你需要明确Windows的默认行为:在使用SMB(Server Message Block)协议连接网络驱动器时,Windows会自动选择支持的最高版本的SMB协议。例如,如果你的Windows客户端和服务器都支持SMB 3.0,那么连接将使用SMB 3.0。如果需要强制使用特定版本的SMB,通常需要在服务器端进行设置,而客户端通常无法直接控制使用的SMB版本。

对于你关于WNetGetNetworkInformation函数的问题,这个函数主要用来获取网络提供者的信息,例如网络提供者的名称和版本,以及网络的性能数据。然而,这个函数并不能直接获取网络驱动器使用的协议和版本。具体如何使用这个函数,你可以查看Microsoft的官方文档。

如果你有特定的安全要求,比如必须使用SMBv3,最好的方式是在服务器端进行设置,确保所有的连接都使用安全的协议和版本。此外,你还可以考虑使用其他的安全机制,例如VPN或者IPSec,来增加网络连接的安全性。

总的来说,这是一个比较复杂的问题,可能需要结合你的具体环境和需求,寻找合适的解决方案。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
WNetAddConnection2是用来连接共享文件夹的函数,它不会确定协议名称和版本,而是由系统自动选择合适的协议。如果需要使用特定的协议,可以通过设置注册表键值来实现。具体来说,可以在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters下创建或修改如下键值:

  • RequireSecuritySignature:设置为1表示只允许使用SMBv2或更高版本的协议,设置为0表示允许使用SMBv1和SMBv2协议。
  • EnableSecuritySignature:设置为1表示要求使用数字签名验证数据包,设置为0表示关闭数字签名验证功能。如果设置为1,连接时会使用SMBv2或更高版本的协议。

WNetGetNetworkInformation函数可以获取一个网络连接的详细信息,包括连接使用的协议类型。具体来说,需要调用该函数并传入一个NETRESOURCE结构体,该结构体包含网络连接的本地名或远程名。如果函数返回成功,可以从NETINFOSTRUCT结构体中获取协议类型和版本信息。

以下是一个示例代码:

#include <Windows.h>
#include <lm.h>
#include <stdio.h>

#pragma comment(lib, "netapi32.lib")

int main()
{
    NETRESOURCE nr = { 0 };
    nr.dwType = RESOURCETYPE_DISK;
    nr.lpRemoteName = L"\\\\192.168.1.1\\share";
    nr.dwScope = RESOURCE_GLOBALNET;
    nr.dwUsage = RESOURCE_CONNECTABLE;

    NETINFOSTRUCT ni = { 0 };
    DWORD dwSize = sizeof(ni);
    DWORD dwResult = WNetGetNetworkInformation(&nr, &ni);
    if (dwResult == NO_ERROR) {
        printf("Protocol: %s, Version: %d.%d\n", ni.szProviderName, HIBYTE(ni.dwNetType), LOBYTE(ni.dwNetType));
    }
    else {
        printf("Error: %d\n", dwResult);
    }

    return 0;
}

在该示例代码中,我们首先创建一个NETRESOURCE结构体,设置它的类型为磁盘类型,远程名称为\\192.168.1.1\share。然后调用WNetGetNetworkInformation函数来获取该网络连接的详细信息。如果函数返回成功,就可以从NETINFOSTRUCT结构体中获取协议类型和版本信息,其中ni.szProviderName即为协议类型。需要注意的是,如果连接使用的是SMBv3协议,那么协议类型也会被返回为"SMB",只有版本信息才能区分不同的SMB版本。
如果我的回答解决了您的问题,请采纳!

以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:

在Windows上确定网络驱动器使用的协议和版本可以通过以下方式:

  1. 使用WNetGetConnection函数获取网络驱动器信息。其中lpRemoteName参数返回的字符串中包含协议信息,如\server\share(SMB)或//server/share(NFS)。
  2. 调用WNetGetUniversalName函数,传入网络驱动器的本地路径。返回的UNIVERSAL_NAME_INFO结构体的lpUniversalName字段包含协议信息。
  3. 检查注册表项HKEY_CURRENT_USER\Network\Connections下的 subkey名称。其中包含协议信息,如SMB或NFS。
  4. 使用WNetGetNetworkInformation函数。传入网络驱动器的本地路径,返回的NETRESOURCE结构体中包含dwType和lpRemoteName字段,可以判断协议类型。

establishing SMB 3.1.1 connection:

  1. 调用WNetAddConnection2函数进行连接。在其lpNetResource参数传入NETRESOURCE结构体,设置以下字段:
- dwType = RESOURCETYPE_DISK
- lpLocalName = 本地驱动器路径(如E:)
- lpRemoteName = \\server\share(表示SMB共享)
- dwFlags = CONNECT_TEMPORARY | CONNECT_REDIRECT
- lpCredentials = 指向凭据结构体的指针,设置用于SMB连接的用户名和密码

  1. 在WNetAddConnection2的dwFlags参数的值中加入CONNECT_SUPPORTED_PROTOCOLS和CONNECT_COMBINE_CONNECTION_PROPERTY_PAGE两个标志。

  2. 调用WNetSetConnectionProperty进行高级属性设置。传入本地驱动器路径,在其dwProperty字段设置WNNC_PREFER_SMBV_30或WNNC_PREFER_SMBV31来指定SMB 3.0或SMB 3.1版本。

  3. 连接成功后,调用WNetGetNetworkConnection函数获取连接信息,检查返回结构体的lpProvider字段是否包含"SMB"以确认连接协议。

C#代码示例:

csharp
NETRESOURCE nr = new NETRESOURCE();
nr.dwType = (int)RESOURCE_CONNECTED;
nr.lpLocalName = "E:";
nr.lpRemoteName = @"\\server\share";
nr.dwFlags = CONNECT_TEMPORARY | CONNECT_REDIRECT;

String username = "user1";
String password = "1234";
String domain = "";

CREDENTIALS crd = new CREDENTIALS();
crd.dwFlags = SEC_WINNT_AUTH_IDENTITY;
crd.UserName = username;
crd.Password = password; 
crd.Domain = domain;

nr.lpCredentials = crd;

uint result = WNetAddConnection2(nr, PASSWORD_CREDENTIALS, null, 0);

// Set SMB 3.1 connection 
uint dwProperty = WNNC_PREFER_SMBV31;
WNetSetConnectionProperty("E:", dwProperty, null); 

NETRESOURCE nr2 = new NETRESOURCE();
nr2.lpLocalName = "E:";
NETRESOURCE[] nra = new NETRESOURCE[1];
nra[0] = nr2;

NETRESOURCE[] nrResult = WNetGetNetworkInformation(nra);
String provider = Marshal.PtrToStringUni(nrResult[0].lpProvider);