如何为CreateFile提供凭据以访问远程共享文件?
解决CreateFile访问远程共享时凭据不生效的问题
核心原因
你遇到的错误1326,是因为Windows默认会复用当前会话中已有的远程主机连接凭据。如果之前存在针对目标主机的其他连接(比如IPC$)使用了进程启动用户的凭据,即使你用NetUseAdd/WNetAddConnection2建立了指定凭据的C$连接,CreateFile仍会优先调用旧的进程凭据。此外,CreateFile本身不支持直接传入凭据,必须通过其他方式指定。
两种可行解决方案
方案1:使用CreateFileWithLogonW直接指定凭据
这是最直接的方法,无需预先建立共享连接,API会自动使用你提供的凭据完成认证并打开文件。
代码示例:
#include <Windows.h> #include <cwchar> void main() { // 远程机器的本地管理员账户信息 const WCHAR* username = L"RemoteAdmin"; const WCHAR* password = L"YourAdminPassword"; const WCHAR* domain = L"10.10.10.10"; // 用远程IP或主机名,本地账户也可填L"." HANDLE hFile = CreateFileWithLogonW( const_cast<WCHAR*>(username), const_cast<WCHAR*>(domain), const_cast<WCHAR*>(password), LOGON32_LOGON_INTERACTIVE, // 交互式登录类型,兼容性更好 nullptr, L"\\\\10.10.10.10\\c$\\windows\\system32\\calc.exe", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ); if (hFile == INVALID_HANDLE_VALUE) { std::wprintf(L"Error: %u\n", GetLastError()); } else { std::wprintf(L"文件打开成功\n"); CloseHandle(hFile); } }
注意事项:
- 若远程机器使用本地账户,
domain参数可填L"."或远程主机名;若为域账户,填对应域名。 LOGON32_LOGON_INTERACTIVE是推荐的登录类型,也可根据需求替换为LOGON32_LOGON_NETWORK。
方案2:清理现有连接后重新建立指定凭据的共享连接
如果必须使用CreateFile,需要先清理目标主机的所有现有共享连接,再用指定凭据建立C$连接,确保CreateFile复用正确的凭据。
代码示例:
#include <Windows.h> #include <cwchar> #include <winnetwk.h> #pragma comment(lib, "mpr.lib") // 链接mpr库 void main() { // 1. 取消目标主机的C$现有连接(如果存在) DWORD cancelResult = WNetCancelConnection2W( L"\\\\10.10.10.10\\c$", 0, TRUE // 强制断开,即使有文件打开 ); // 2. 用指定凭据建立C$连接 NETRESOURCEW netRes = {0}; netRes.dwType = RESOURCETYPE_DISK; netRes.lpRemoteName = L"\\\\10.10.10.10\\c$"; DWORD connResult = WNetAddConnection2W( &netRes, L"YourAdminPassword", L"10.10.10.10\\RemoteAdmin", // 格式:远程主机名/IP\用户名 0 ); if (connResult != NO_ERROR) { std::wprintf(L"WNetAddConnection2失败:%u\n", connResult); return; } // 3. 调用CreateFile,此时会复用刚建立的C$连接凭据 HANDLE hFile = CreateFileW( L"\\\\10.10.10.10\\c$\\windows\\system32\\calc.exe", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr ); if (hFile == INVALID_HANDLE_VALUE) { std::wprintf(L"Error: %u\n", GetLastError()); } else { std::wprintf(L"文件打开成功\n"); CloseHandle(hFile); } // 4. 用完后断开连接 WNetCancelConnection2W(L"\\\\10.10.10.10\\c$", 0, TRUE); }
关键说明:
- 必须先清理现有连接,避免Windows复用旧的进程凭据。
WNetAddConnection2的用户名必须包含远程主机标识(如10.10.10.10\RemoteAdmin),确保是远程机器的本地账户。
内容的提问来源于stack exchange,提问作者Bogudan
相关产品推荐
相关产品推荐

