You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中利用Windows已保存凭据访问局域网共享文件夹

如何在C#中利用Windows暂存凭据访问局域网共享文件夹?

问题描述

我正在开发一款需要访问局域网共享文件夹、进行文件读取与修改操作的应用,但不想要求用户输入凭据。若用户此前已使用凭据访问过该共享文件夹,能否借助Windows的凭据暂存功能(重启前有效)?是否可通过C#“获取”/使用这些凭据或“配置文件”来访问共享位置?

我当前的实现方式是请求用户提供凭据后进行模拟登录,但希望能避免这种方式:

token = IntPtr.Zero;
var success = LogonUser(machine_username, remote_machine, machine_password, 9, 0, ref token);
using (WindowsImpersonationContext person = new WindowsIdentity(token).Impersonate())
{
    try
    {
        // do something on the network location
    }
    catch (IOException)
    {
        Console.WriteLine("Connection with the server failed!");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    finally
    {
        person.Undo();
        CloseHandle(token);
    }
}

解决方案

当然可以!Windows会自动暂存用户最近访问共享资源时输入的凭据(重启前有效),只要你的应用运行在当前用户的登录会话中,就能直接利用这个缓存来访问共享,完全不需要手动获取或存储凭据。

1. 核心思路:利用Windows网络连接API自动复用凭据

不需要使用LogonUser做用户模拟,而是调用Windows原生的WNetAddConnection2 API——这个API会自动尝试使用当前用户凭据缓存中的信息来建立共享连接,无需手动传入用户名和密码。

2. C#实现代码示例

首先需要引入API的DllImport声明,然后调用它来建立共享连接:

using System;
using System.Runtime.InteropServices;

public class NetworkShareHelper
{
    // 定义WNetAddConnection2需要的结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct NETRESOURCE
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        public string lpLocalName;
        public string lpRemoteName;
        public string lpComment;
        public string lpProvider;
    }

    // 导入WNetAddConnection2 API
    [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int WNetAddConnection2(ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

    // 导入WNetCancelConnection2 API用于断开连接(可选)
    [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int WNetCancelConnection2(string lpName, int dwFlags, bool fForce);

    public static bool ConnectToShare(string sharePath)
    {
        NETRESOURCE resource = new NETRESOURCE
        {
            dwType = 0x00000001, // 资源类型为磁盘
            lpRemoteName = sharePath
        };

        // 调用API,用户名和密码传null,自动使用缓存凭据
        int result = WNetAddConnection2(ref resource, null, null, 0);
        return result == 0; // 返回0表示成功
    }

    public static bool DisconnectFromShare(string sharePath)
    {
        int result = WNetCancelConnection2(sharePath, 0, true);
        return result == 0;
    }
}

// 使用示例
public class Program
{
    public static void Main()
    {
        string sharePath = @"\\servername\sharedfolder";
        if (NetworkShareHelper.ConnectToShare(sharePath))
        {
            try
            {
                // 在这里执行文件读取/修改操作,比如:
                string[] files = System.IO.Directory.GetFiles(sharePath);
                foreach (var file in files)
                {
                    Console.WriteLine(file);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"操作失败:{ex.Message}");
            }
            finally
            {
                NetworkShareHelper.DisconnectFromShare(sharePath);
            }
        }
        else
        {
            Console.WriteLine("无法连接到共享文件夹,请检查是否已访问过该共享或凭据是否有效。");
        }
    }
}

3. 关键注意事项

  • 会话一致性:确保你的应用是在用户登录的交互式会话中运行,不要以服务身份运行——服务通常运行在独立的会话,无法访问当前用户的凭据缓存。
  • 降级处理:如果凭据缓存中没有对应共享的凭据,WNetAddConnection2会返回错误,这时你可以选择提示用户输入凭据(作为降级方案),但大部分场景下,用户之前访问过的话就能直接复用缓存。
  • 权限问题:应用运行的用户需要有访问该共享文件夹的权限,缓存的凭据也必须对应有权限的账户。

内容的提问来源于stack exchange,提问作者CameFromSpace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:29:01