在过时的复制合作伙伴上手动删除挥之不去的对象

本文有助于在将过时的域控制器(DC)或全局编录服务器重新联机后手动删除 挥发对象 。 在许多情况下,可以使用命令或工具(如 Lingering Object Liquidator)清理挥之不去的对象repadmin /removelingeringobjects。 但是,如果放弃 了对象,这些设施不起作用。

原始 KB 数: 314282

在域控制器或全局编录服务器长时间脱机后重新联机时,可能会出现以下任何问题:

  • 电子邮件不会传递到用户对象在域之间移动的用户。 将过时的域控制器或全局目录服务器重新联机后,用户对象的两个实例会显示在全局目录内容中。 这两个对象具有相同的电子邮件地址,因此无法传递电子邮件。
  • 不再存在的用户帐户仍显示在全局地址列表中。
  • 不再存在的通用组仍显示在用户的访问令牌中。

脱机持续时间长于逻辑删除生存期设置的值

已脱机超过逻辑删除生存期设置值(默认值为 60 或 180 天)的域控制器或全局编录服务器可能包含在其他域控制器或全局编录服务器上删除的对象。 此外,这些对象的墓碑可能不再存在。 将过时的域控制器重新联机时,无法收到对象删除的通知。 如果修改了任何对象,则会在域的其余部分重新激活它们。

对于复制到读/写命名上下文中的对象,标准行为(松散复制一致性)是接收域控制器重新创建本地数据库目录信息树(DIT)中尚不存在的对象。 然后将这些对象复制回原始域控制器,从而有效地重新创建已删除的对象。 如果 Active Directory 中不应存在该对象(例如,如果对象由过时的域控制器重新引入),则可以使用标准工具(如 ADSIEdit 或 Active Directory 用户和计算机 管理单元)删除这些对象。

删除读取/写入命名上下文的挥发对象非常简单。 本文介绍如何删除已出现在全局目录(只读)命名上下文中的挥发对象。

获取可分辨名称并标识域

确定对象所在的域(因此,具有对象读/写副本的域控制器的名称)的最佳方法是建立对象的可分辨名称。 为此,可以使用Ldp.exe工具搜索重复用户、组或通讯组列表的名称(或名称的一部分):

  1. 启动 Ldp.exe

  2. “连接 ”菜单上,选择“ 连接”。

  3. 输入全局目录服务器的名称。 输入 3268 作为要连接的端口。 选择“确定”

  4. “连接 ”菜单上,选择“ 绑定”。 如果当前凭据不足以查询所有全局目录内容,请输入有效的凭据。 选择“确定”

  5. “视图 ”菜单上,选择“ ”。 输入林根的可分辨名称。 选择“确定”

  6. 右键单击树列表中的林根目录,然后选择“ 搜索”。

  7. 创建以下窗体的筛选器:

    (attribute=value)

    将属性替换为相应的数据。 例如,若要创建一个筛选器以返回结果,其中 sAMAccountName 属性的值设置为名为 testuser用户帐户,请在筛选器框中输入 (sAMAccountName=testuser)。 cnuserPrincipalName、sAMAccountNamenamemailsn 属性是查找用户对象的有用候选项。 对于组对象,请使用 cnsAMAccountName名称 属性。 如有必要, 可以在值 字段中使用星号 \ 。

    有关轻型目录访问协议 (LDAP) 筛选器语法的详细信息,请参阅 搜索筛选器语法

  8. 选择“子树作为搜索范围。

  9. 选择“选项”。“搜索选项”对话框中,移动到“属性”控件的末尾。

  10. 将 objectGUID 追加到列表中。 选择“确定”

  11. 选择“运行”以运行查询。

  12. 查看结果。 必须标识应从全局编录服务器中删除哪些显示的对象。 发现有问题的对象的一个指示是,该对象不存在于命名上下文的读/写副本上。

  13. 根据需要重新运行查询并重新运行。

  14. 如果标识了挥之不去的对象,请记下其可分辨名称和 objectGUID

获取对象的可分辨名称后,通过查看 可分辨名称的 dc= 部分来确定它所在的域。 例如,cn=FirstName LastName,cn=Users,dc=contoso,dc=com 的域 contoso.com 接下来,找到域的域控制器(也可以是全局目录服务器)。

repadmin /showreps <dcname>运行命令(你<dcname>所在的域控制器的名称)。 从输出中,记下域控制器的 objectGuid

控制台
C:\>repadmin /showreps some-DC
Your-Site\some-DC
DSA Options : (none)
objectGuid : <GUID>

如果只有少数对象和全局编录服务器,请删除挥之不去的对象

如果只有几个对象和全局编录服务器,请按照下列步骤使用Ldp.exe删除对象

  1. 使用企业管理员凭据登录到包含挥发对象副本的每个全局编录服务器。

  2. 开始Ldp.exe并连接到本地域控制器上的端口 389(将服务器框留空)。

  3. “连接 ”菜单上,选择“ 绑定”。 将所有框留空(你已以企业管理员身份登录)。

  4. “浏览 ”菜单上,选择“ 修改”。

  5. Dn 框留空。

  6. “属性 ”框中,输入 RemoveLingeringObject

  7. 输入 <GUID= 作为值。

  8. 追加前面从命令 repadmin /showreps <dcname>获取的域控制器的 GUID。

    备注

    在此示例中,是一个域控制器, <dcname> 用于托管挥之不去对象的可写命名上下文。

  9. Append > : <GUID=. 不要省略空格。

  10. 追加挥发对象的 GUID。

  11. 追加 >

  12. 完整值应如下所示: <GUID=GUID> : <GUID=GUID>

  13. 选择“替换”操作,然后选择接口上的 Enter。 现在命令会显示在 条目列表中

  14. 选择“ 运行” 以运行请求。 Ldp.exe窗口右侧包含请求结果。 它应当与以下示例类似:

    输出
    ***Call Modify...
    ldap_modify_s(ld, '(null)',[1] attrs);
    Modified "".
    

如果有多个对象和全局编录服务器,请删除挥之不去的对象

如果有多个要删除的对象和许多全局编录服务器,则使用以下脚本可能更方便:

  1. 将以下文本粘贴到新文件夹中名为 Walkservers.cmd 的新文件中:

    控制台
    for /f %%j in (server-list.txt) do walkobjects %%j
    
  2. 将以下文本粘贴到名为 Walkobjects.cmd的文件中:

    控制台
    for /f "delims=@" %%i in (object-list.txt) do cscript //NoLogo MODIFYROOTDSE.VBS %1 "%%i" >>update-%1.log
    

    备注

    这是一个命令行。 此处插入换行符,便于阅读。

  3. 将以下文本粘贴到名为 Modifyrootdse.vbs 的文件中:

    Visual Basic 脚本
    '********************************************************************
    '*
    '* File:        MODIFYROOTDSE.VBS
    '* Created:     January 2002
    '* Version:     1.0
    '*
    '* Main Function: Writes Active Directory information to clean up 
    '* objects as per: Q314282.
    '* Usage: Modifyrootdse.vbs <TargetServer> <GUID PAIR>
    '* Parameter are fed into the script using a pair of batch files.
    '*
    '* Copyright (C) 2002 Microsoft Corporation
    '*
    '********************************************************************
    
    OPTION EXPLICIT
    ON ERROR RESUME NEXT
    
    Dim objDomain
    Dim ObjValue, strServerName, adsLdapPath 
    Dim i
    
    'Get the command-line arguments
        if Wscript.arguments.count <> 2 Then
         Print "Invalid Number of Parameters. Use with WalkServers.CMD and WalkObjects.CMD"
        WScript.quit
    End If
    
        strServerName = Wscript.arguments.item(0)
        ObjValue = Wscript.arguments.item(1)
    
        adsLdapPath = "LDAP://" & strServerName & "/RootDSE"
    
        Set objDomain = GetObject(adsLdapPath)
        If Err.Number <> 0 Then
            WScript.Echo "Error opening ROOTDSE. Error number is: " & Err.Number & ". Error description is: " & Err.Description & "."
        Set objDomain = Nothing
            WScript.quit
        End If
    
        objDomain.Put "RemoveLingeringObject", ObjValue
        objDomain.Setinfo
    
        If Err.Number = 0 Then
           WScript.Echo "Object " & ObjValue & " was removed."
    Else
           WScript.Echo "Object " & ObjValue & " could not be removed. Error number is: " & Err.Number & ". Error description is: " & Err.Description & "."
        End If
    WScript.Quit
    

    备注

    如果手动启动 Modifyrootdse.vbs ,请确保将包含空格的任何参数括在引号中。

  4. 创建包含挥发对象的所有全局编录服务器的列表。 将服务器名称放在同一 文件夹中Server-list.txt 文件中。 使用完全限定的域名来避免 DNS 后缀搜索。

  5. 将此过程前面获取的 GUID 对添加到 Object-list.txt 文件中。 每行添加一对。 使用以下语法:

    <GUID = <DC GUID>> : <GUID = <object GUID>>

    此处,第一个值是可写域控制器的 GUID,用于确认原始对象不再存在。 第二个值是要删除的挥发对象的 GUID。

  6. 运行Walk-servers.cmd文件。 这些脚本为Server-list.txt文件中列出的每个全局编录服务器生成一个名为Update-server-name.log日志文件。 日志文件包含要删除的每个对象的行。

备注

日志文件中的错误不一定表示问题,因为所有全局编录服务器上都可能不存在挥之不去的对象。 但是,“操作被拒绝”或“操作错误”形式的错误消息表示 GUID 或值语法存在问题。 如果发生这些错误,请验证以下项:

  • 请确保域控制器 GUID 是包含包含该对象的域的可写副本的域控制器的正确 GUID。
  • 确保对象 GUID 标识全局编录(只读)命名上下文中的挥发对象。

运行Walkservers.cmd以修改环境中许多挥之不去的对象时出现错误消息

对象 <GUID=GUID> : <无法删除 GUID=GUID> 。 错误号为:-2147016672。 错误说明为:.

发生此错误的原因是脚本针对域控制器的 GUID 运行,该域控制器不包含包含挥之不去对象的可写分区。 使用Ldp.exe工具验证徘徊对象的位置。

示例

在以下示例中,导致删除错误消息的挥发对象位于 corp.company.local 域中。 但是,<GUID=<GUID>>objects-list.txt文件中的域控制器与域中没有可写分区的corp.company.local域控制器company.local相关联。

输出
ldap_search_s(ld, "DC=company,DC=local", 2, "(cn=User*)", attrList,  0, &msg)
Result <0>: (null)
Matched DNs: 
Getting 4 entries:
>> Dn: CN=User\, Joe,OU=Exec,OU=Corporate Users,DC=corp,DC=company,DC=local
    1> canonicalName: corp.company.local/Corporate Users/Exec/User, Joe; 
    1> cn: User, Joe; 
    1> description: CEO; 
    1> displayName: User, Joe; 
    1> distinguishedName: CN=User\, Joe,OU=Exec,OU=Corporate Users,DC=corp,DC=company,DC=local; 
    4> objectClass: top; person; organizationalPerson; user; 
    1> objectGUID: <GUID>; 
    1> name: User, Joe; 
>> Dn: CN=User\, Joe,OU=Migration,DC=corp,DC=company,DC=local
    1> canonicalName: corp.company.local/Migration/User, Joe; 
    1> cn: User, Joe; 
    1> description: Disabled Account; 
    1> displayName: User, Joe; 
    1> distinguishedName: CN=User\, Joe,OU=Migration,DC=corp,DC=company,DC=local; 
    4> objectClass: top; person; organizationalPerson; user; 
    1> objectGUID: <GUID>; 
    1> name: User, Joe; 

运行以下命令获取域中服务器的 corp.company.local GUID:

控制台
repadmin /showreps <dcname>

在此命令中, <dcname> 是域中域控制器 corp.company.local 名称的占位符。 更改Objects-list.txt文件中的 GUID 以匹配域中域控制器corp.company.local的 GUID。 在此示例中, Objects-list.txt 文件将显示为:

<GUID=<GUID>> : <GUID=<GUID>>

第一个 <GUID> 是域中域控制器 corp.company.local 的 GUID。 第二 <GUID> 个是 LDAP 搜索中挥之不去对象的 GUID。

运行 Walk-servers.cmd时,该命令现在成功完成,而不会出现“-2147016672”错误。

如果无法使用这些方法解决日志文件中的错误,则可能遇到其他问题。 请联系Microsoft产品支持服务获取其他帮助。