收到错误消息时无法访问 WMI "Windows cannot connect to the domain"



所以我有一个XP Pro工作站报告"Windows无法连接到域,因为域控制器关闭或不可用,或者因为找不到您的计算机帐户。请稍后重试。如果此消息继续出现,请与系统管理员联系以获取帮助。使用域凭据登录时。要手动解决此问题,我只需使用本地管理员帐户登录,将其拖放到工作组,然后将其重新添加到域中。然而,考虑到这个问题在我的工作中经常出现,这个过程可能需要相当长的时间。我正在尝试做的是以编程方式自动化删除/重新加入过程。以下代码有效,但前提是计算机正确位于域或工作组中,而不是像现在这样处于不确定状态。

Const JOIN_DOMAIN             = 1
Const ACCT_CREATE             = 2
Const ACCT_DELETE             = 4
Const WIN9X_UPGRADE           = 16
Const DOMAIN_JOIN_IF_JOINED   = 32
Const JOIN_UNSECURE           = 64
Const MACHINE_PASSWORD_PASSED = 128
Const DEFERRED_SPN_SET        = 256
Const INSTALL_INVOCATION      = 262144
Const WbemAuthenticationLevelPktPrivacy = 6
'On Error Resume Next 
SystemName = "SystemName"
strNamespace = "rootcimv2"
ComputerBLogin = "LoginB"
ComputerBPass = "PassB"
ComputerALogin = "LoginA"
ComputerAPass = "PassA"
DomainName = "domain.com"
OU = "OU=desiredou,DC=domain,DC=com"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\" & SystemName & "rootcimv2")
If Err.Number <> 0 Then
    Set objWbemLocator = CreateObject("WbemScripting.SWbemLocator")
    Set objWMIService = objwbemLocator.ConnectServer(SystemName, strNamespace, ComputerBLogin, ComputerBPass)
    objWMIService.Security_.authenticationLevel = WbemAuthenticationLevelPktPrivacy
    Err.Clear
End IF
Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
For Each objComputer in colComputers
    Return = objComputer.UnJoinDomainOrWorkGroup(NULL, NULL)
    Return = objComputer.JoinDomainOrWorkGroup("WORKGROUP", NULL, NULL)
    If Err.Number <> 0 Then
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup (SystemName & " could not be dropped to the workgroup!" & vbCr &_
                "Error: " & Err.Description,, "Title", 0 + 16)
    Else
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup (SystemName & " was successfully dropped to the WORKGROUP!",, "Title", 0 + 64)
    End If
Next
For Each objComputer in colComputers
    ReturnValue = objComputer.JoinDomainOrWorkGroup(DomainName, ComputerAPass, ComputerALogin, OU, JOIN_DOMAIN + ACCT_CREATE)
    If Err.Number <> 0 Then
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup ("Unable to join " & SystemName & " to the domain! Please join manually.",, "Title", 0 + 16)
    Else
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup ("Domain joining was successful!",, "Title", 0 + 64)
    End If
Next

当脚本到达第 24 行时:

Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\" & SystemName & "rootcimv2")

它错误为"远程服务器计算机不存在或不可用:'GetObject'"。如果计算机正确位于域中,则此行通常有效。AD 对象确实存在。如果出现此错误,我将其编码为使用第 29 行的本地管理员凭据登录计算机:

Set objWMIService = objwbemLocator.ConnectServer(SystemName, strNamespace, ComputerBLogin, ComputerBPass)

这将错误地显示"SWbemLocator:访问被拒绝"。

因此,使用我熟悉的这两种方法,当机器处于这种困境时,无法访问 WMI。在我的研究中,似乎"工作站和域之间的信任关系失败了",但对我来说,这并不能解释为什么我无法使用本地管理员凭据登录。

我不想求助于NETDOM,但我还是尝试了。谈论失败的信任关系也是错误的。

所以我的问题是:
A) 当出现此错误消息时,是否有任何方法以编程方式将工作站拖放到工作组并将其重新添加到域中?
B) 以编程方式修复工作站和域之间的信任关系(如果这实际上是它有什么问题)?
C) 出现此错误消息时,请使用管理员凭据登录工作站?

提前感谢大家的任何潜在帮助,如果需要更多详细信息,请告诉我。

好吧,我觉得有点愚蠢,没有早点想到这一点,但 Lizz 提到映射驱动器让我思考。我尝试映射驱动器,但它一直希望使用我当前的凭据或具有备用域用户名的域。所以我尝试了".\LoginB",但这只使用了我的计算机名称,后跟"LoginB"。我最终不得不使用"系统名称\登录B"并成功映射驱动器。使用它,我能够通过将 ComputerBLogin 变量更改为以下内容来更正上面的代码,这实际上确实有效:

Const JOIN_DOMAIN             = 1
Const ACCT_CREATE             = 2
Const ACCT_DELETE             = 4
Const WIN9X_UPGRADE           = 16
Const DOMAIN_JOIN_IF_JOINED   = 32
Const JOIN_UNSECURE           = 64
Const MACHINE_PASSWORD_PASSED = 128
Const DEFERRED_SPN_SET        = 256
Const INSTALL_INVOCATION      = 262144
Const WbemAuthenticationLevelPktPrivacy = 6
On Error Resume Next 
SystemName = "SystemName"
strNamespace = "rootcimv2"
ComputerBLogin = SystemName & "LoginB"
ComputerBPass = "PassB"
ComputerALogin = "LoginA"
ComputerAPass = "PassA"
DomainName = "domain.com"
OU = "OU=desiredou,DC=domain,DC=com"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\" & SystemName & "rootcimv2")
If Err.Number <> 0 Then
    Set objWbemLocator = CreateObject("WbemScripting.SWbemLocator")
    Set objWMIService = objwbemLocator.ConnectServer(SystemName, strNamespace, ComputerBLogin, ComputerBPass)
    objWMIService.Security_.authenticationLevel = WbemAuthenticationLevelPktPrivacy
    Err.Clear
End IF
Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
For Each objComputer in colComputers
    Return = objComputer.UnJoinDomainOrWorkGroup(NULL, NULL)
    Return = objComputer.JoinDomainOrWorkGroup("WORKGROUP", NULL, NULL)
    If Err.Number <> 0 Then
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup (SystemName & " could not be dropped to the workgroup!" & vbCr &_
                "Error: " & Err.Description,, "Title", 0 + 16)
    Else
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup (SystemName & " was successfully dropped to the WORKGROUP!",, "Title", 0 + 64)
    End If
Next
For Each objComputer in colComputers
    ReturnValue = objComputer.JoinDomainOrWorkGroup(DomainName, ComputerAPass, ComputerALogin, OU, JOIN_DOMAIN + ACCT_CREATE)
    If Err.Number <> 0 Then
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup ("Unable to join " & SystemName & " to the domain! Please join manually.",, "Title", 0 + 16)
    Else
        Set WshShell = CreateObject("WScript.Shell")
        message = WshShell.Popup ("Domain joining was successful!",, "Title", 0 + 64)
    End If
Next

感谢您的灯泡时刻 Lizz!

据我所知,当主机处于这种状态时,与主机及其域的关系无法修复; 我们从来没有能够预测地做到这一点。为此,还需要在脚本中对本地管理员和 Active Directory 帐户凭据进行硬编码,这是一个非常危险的过程。

相反,您必须使用域凭据从 AD 中删除主机,然后重新启动主机。也许在将其从 AD 中删除后,您将能够使用本地管理员凭据登录它。出于测试目的复制此条件的一种方法是删除测试电脑的域对象,然后重新启动并查看是否可以进行身份验证。

最后,这可能是只能通过交互方式完成的事情。而且我不会使用 WMI,因为 WMI 比其他方法具有更多的安全检查和限制,例如使用 RPC 启动 psexec 会话以在损坏的主机上复制和运行脚本。

上面链接中的脚本会提示您输入 AD 凭据。此链接假定您正在使用这些信誉运行脚本,如下所示。

strComputer = "atl-pro-040"
set objComputer = GetObject("LDAP://CN=" & strComputer & _
    ",CN=Computers,DC=fabrikam,DC=com")
objComputer.DeleteObject (0)

相关内容

最新更新