Delphi应用访问LAN受保护共享文件夹的两类问题求助
解决Delphi 10.2.3访问带权限局域网共享的两个问题(Windows 10)
问题原因分析
ERROR_SESSION_CREDENTIAL_CONFLICT(计算机名路径连接失败):系统已存在到目标服务器的凭据会话(比如之前用不同用户访问过,或系统缓存了旧凭据),新连接的凭据与现有会话冲突。直接连接共享文件夹而非服务器根路径,也会增加触发该错误的概率。- 断开不生效(IP路径连接后):
WNetCancelConnection2仅断开指定的共享文件夹,但系统仍保留与服务器的底层会话连接,导致资源管理器可通过会话继续访问。若存在未彻底关闭的文件句柄,即使指定强制断开参数,也无法清除残留会话。
解决方案及代码修正
核心修正点
- 先断开目标服务器的所有现有连接,再发起新连接,避免凭据冲突
- 优先连接服务器根路径(如
\\server-pc),而非具体共享文件夹 - 使用
CONNECT_TEMPORARY标志创建临时连接,避免持久化凭据到系统 - 断开时先关闭所有文件句柄,再依次断开共享文件夹和服务器会话
修正后的完整代码
uses Windows, SysUtils, Classes, Forms, Dialogs; const CONNECT_TEMPORARY = $00000004; CONNECT_UPDATE_PROFILE = $00000001; function AddRemoteConnection(const RemoteServer, UserName, Password: string): DWORD; var nr: TNetResource; begin ZeroMemory(@nr, SizeOf(nr)); nr.dwType := RESOURCETYPE_DISK; // 连接服务器根路径,而非具体共享文件夹,减少凭据冲突 nr.lpRemoteName := PWideChar(RemoteServer); nr.lpLocalName := nil; nr.lpProvider := nil; // 先尝试断开服务器的现有连接,清理冲突会话 WNetCancelConnection2(PWideChar(RemoteServer), CONNECT_UPDATE_PROFILE, True); // 创建临时连接,不持久化到系统配置文件 Result := WNetAddConnection2(nr, PWideChar(Password), PWideChar(UserName), CONNECT_TEMPORARY); end; procedure RemoveRemoteConnection(const RemoteServer, RemoteShare: string); begin // 先断开具体共享文件夹 WNetCancelConnection2(PWideChar(RemoteShare), 0, True); // 再断开服务器级别的会话,确保彻底断开 WNetCancelConnection2(PWideChar(RemoteServer), CONNECT_UPDATE_PROFILE, True); end; procedure TForm8.Button1Click(Sender: TObject); var f: TextFile; dwResult: DWORD; serverPath, sharePath, un, pw: string; begin serverPath := '\\server-pc'; sharePath := '\\server-pc\testfolder'; // 切换到IP路径的话,只需修改以下两行: // serverPath := '\\192.168.0.1'; // sharePath := '\\192.168.0.1\testfolder'; un := 'theuser'; pw := 'thepassword'; dwResult := AddRemoteConnection(serverPath, un, pw); if dwResult = NO_ERROR then begin try AssignFile(f, sharePath + '\test.txt'); try Rewrite(f); Writeln(f, 'xxxx'); finally CloseFile(f); // 短暂延迟,确保文件句柄彻底释放 Sleep(100); end; finally RemoveRemoteConnection(serverPath, sharePath); end; end else ShowMessage('连接错误:' + SysErrorMessage(dwResult)); end;
额外注意事项
- 若仍存在凭据冲突,可手动打开Windows凭据管理器,删除目标服务器的相关凭据;或使用
CredDeleteAPI在代码中清理(需管理员权限) CONNECT_TEMPORARY标志确保连接不会在系统重启后保留,减少会话残留问题- 操作文件后务必确保
CloseFile执行完成,必要时添加短暂延迟,避免文件句柄未释放导致断开失败
内容的提问来源于stack exchange,提问作者Roberto Nicchi
相关产品推荐
相关产品推荐

