【问题标题】:Why WNetAddConnection2 still returns 1219 after successfully calling WNetCancelConnection2?为什么成功调用 WNetCancelConnection2 后 WNetAddConnection2 仍然返回 1219?
【发布时间】:2012-07-15 15:54:21
【问题描述】:

我编写了一些代码来连接远程服务器上的某个共享。如果WNetAddConnection2返回ERROR_SESSION_CREDENTIAL_CONFLICT(1219),我会先取消WNetCancelConnection2的连接(返回NO_ERROR)。然后重新连接。但是WNetAddConnection2 仍然返回1219。 为什么会这样以及如何解决?

这是我的代码

BOOL ADDirectorySearch::IPCConnect(CString strServerName, CString strDomainName, CString strUserName, CString strPassWord)
{
    CString strServerNameWithSlash = _T("\\\\") + strServerName; //actually is \\klbnt
    CString strFullUserName = strDomainName + _T("\\") + strUserName; //is domaintest\administrator
    _bstr_t bstrServerNameWithSlash = strServerNameWithSlash;
    _bstr_t bstrFullUserName = strFullUserName;
    _bstr_t bstrPassWord = strPassWord;
    DWORD dwResult;
    NETRESOURCEW netResource;
    memset(&netResource, 0, sizeof(netResource));
    netResource.dwScope = RESOURCE_GLOBALNET;  
    netResource.dwType = RESOURCETYPE_DISK;
    netResource.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;  
    netResource.dwUsage = RESOURCEUSAGE_CONNECTABLE;
    netResource.lpProvider = L"";
    netResource.lpRemoteName = bstrServerNameWithSlash;//Remote IP like:\\192.168.1.11
    dwResult = WNetAddConnection2W(&netResource, bstrPassWord, bstrFullUserName, CONNECT_INTERACTIVE);
    if (dwResult == ERROR_SESSION_CREDENTIAL_CONFLICT)
    {
        dwResult = WNetCancelConnection2W(bstrServerNameWithSlash, CONNECT_UPDATE_PROFILE, TRUE);
        if (dwResult == NO_ERROR)
        {
            dwResult = WNetAddConnection2W(&netResource, bstrPassWord, bstrFullUserName, CONNECT_INTERACTIVE);
        }
        else
        {
            //MyMessageBox_Error(_T("IPCConnect Error."), _T("Error"));
            return FALSE;
        }
    }
    if (dwResult == NO_ERROR)
    {
        return TRUE;
    }
    else
    {
        //MyMessageBox_Error(_T("IPCConnect Error."), _T("Error"));
        return FALSE;
    }
}

仅供参考:在cmd中输入“net use”后,我得到了这个,我觉得有什么错误:

Status       Local     Remote                    Network

-------------------------------------------------------------------------------
OK                     \\klbnt\NRDC1001          Microsoft Windows Network
The command completed successfully.

【问题讨论】:

  • 您没有设置 resource.lpLocalName。在 sn-p 中看不到 WNetCancelConnection2()。
  • 您可能需要在 WNetCancelConnection2 中指定共享名称以及服务器名称,即 \\klbnt\NRDC1001 而不仅仅是 \\klbnt
  • 我将 lpLocalName 设置为 "" 但没有任何改变。 WNetCancelConnection2 在我的代码中的 2 个 WNetAddConnection2 调用之间被调用。另外连接\\klbnt和\\klbnt\nrdc1001有什么关系?与 \\klbnt 的连接是否隐含包含与所有 klbnt 共享的连接?还是彼此什么都没有?我只是想授予我的进程访问远程共享的权限,那么这样做的正确方法是什么?

标签: c++ windows winapi active-directory


【解决方案1】:

我现在刚刚遇到这个问题,基本上似乎是由于另一个进程仍在打开文件,即使我将"true"指定为WNetCancelConnection2()的最后一个参数强制关闭连接。一旦我关闭了其他进程,我就能够在凭据连接和重新连接到同一个共享之间成功切换。这是在 Windows 2012(64 位)上,共享是本地的(由机器名引用)。

但是...如果您想连接到同一台机器上的不同共享,这仍然是个问题。如果我尝试以user1 连接到\\mymachine\share1,然后以user2 连接到\\mymachine\share2,我会收到1219 错误(即使它处于完全不同的过程中)。我必须在\\mymachine\share1 上显式调用WNetCancelConnnection,然后才能连接到share2,这意味着在您连接到特定机器上的共享时,您可能必须首先枚举现有连接并关闭每个连接。

比较郁闷,看不懂这里的设计原理。似乎创建临时连接等的标志对这种行为也没有影响。我真正想做的是说“对于这个线程,连接到这台机器上的这个共享并作为这个用户,这样所有访问共享上的文件的尝试都是用那个用户的凭据完成的”。这样其他进程/线程正在执行的操作不会导致当前进程/线程出现问题。

【讨论】:

  • 应该可以使用LogonUserExLOGON32_LOGON_NEW_CREDENTIALS 来获得一个单独的登录会话来连接到远程服务器。但是,我不确定模拟是否会起作用,或者您是否需要使用新令牌启动一个实际的子流程并从那里开始工作。
  • 我最初是从使用模拟开始的,但它使尝试访问我需要的所有其他资源(例如数据库)成为真正的 PITA!
  • 模拟可以根据需要打开和关闭,所以这应该不是问题。一种方法是将驱动器号映射到共享,一旦驱动器号被映射,您就可以关闭模​​拟并仍然使用驱动器号。
  • 就我而言,我只需要知道是否没有任何活动连接。我使用了 WMI 命名空间 MSFT_SmbConnection。即使在 WNetCancelConnection2 之后,它也能够显示活动的 SMB 连接。 docs.microsoft.com/en-us/previous-versions/windows/desktop/smb/… powershell cmdlet Get-SmbConnection 还显示活动连接。
猜你喜欢
  • 1970-01-01
  • 2014-04-21
  • 2020-03-30
  • 2016-09-30
  • 2020-02-04
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多