PowerShell Version 2.0 script to fix "legacy" values of a specified attribute of an Active Directory object. This allows the object attribute to take advantage of Link Value Replication (LVR). If the values of the attribute were assigned before the forest functional level was at least Windows Server 2003, the attribute may not take advantage of link value replication (LVR). These values are called "legacy". Without LVR, any updates to the attribute of the object requires that the entire attribute be replicated. For example, if a group has 1000 members, and you add one more, all 1001 values must be replicated. With LVR, only the updated or new values are replicated.

The script prompts for the sAMAccountName or distinguished name (DN) of the object, the lDAPDisplayName of the attriubte, and a text file containing the output from the repadmin command. This file can be created at the command prompt of a domain controller with a statement similar to:

repadmin /showobjmeta mydc "cn=My Object,ou=West,dc=domain,dc=com" > report.txt

where "mydc" is the host name of a domain controller and the distinguished name is that of the object to be processed. The file "report.txt" contains the output and is the file the script prompts for.

The script first checks that the object exists in Active Directory. Then the script parses the file for lines containing the string "LEGACY". This means the repadmin tool identified the value of a linked multi-valued attribute that does not take advantage of LVR. The script parses this line for the lDAPDisplayName of the attribute to make sure it matches the one specified. Then the script reads the value of the attribute on the next line. This value is added to an array of values. The script uses this array with the -Remove parameter of the Set-ADObject cmdlet to remove all such identified values from the attribute of the object. Finally. after a short pause, the script uses the -Add parameter of the Set-ADObject cmdlet to add the values back into the attribute of the object.

When the script has finished, all values that repadmin previously identified as "LEGACY" will now be identified as "PRESENT". This means they take advantage of link value replication.


# FixLegacyValues.ps1 
# PowerShell Version 2 script to fix "Legacy" values of a specified object. 
# This allows the object to take advantage of Link Value Replication (LVR) 
# for all values after the Forest Functional Level (FFL) is raised from 
# Windows 2000 Server to Windows Server 2003 (or above). 
# Author: Richard L. Mueller 
# This script prompts for the sAMAccountName or DN of the object, the 
# lDAPDisplayName of the attribute,  and a text file containing the output 
# from the repadmin command. This file can be created at the command prompt 
# of a domain controller with a statement similar to: 
# repadmin /showobjmeta mydc "cn=My Object,ou=West,dc=domain,dc=com" > report.txt 
# where mydc is the host name of a domain controller and the distinguished 
# name is that of the object to be processed. The script processes the values 
# in blocks of 4000 at most, to avoid excessive network traffic. 
# Version 1.0 - September 22015 
# Version 2.0 - September 72015 - Process values in blocks of 4000 at most. 
# Modify the server name to match the DNS Name of a domain controller in your domain. 
$Server = mydc.domain.com 
# Prompt for the object. 
$ADObjectName = Read-Host "Enter the object sAMAccountName or distinguishedName" 
Import-Module ActiveDirectory 
# Make sure the object exists on the specified domain controller. 
$ADObject = $Null 
If ($ADObjectName -Like "*,*"{ 
    # $ADObjectName is the distinguished name of an object. 
    $ADObject = Get-ADObject -Identity $ADObjectName -Server $Server 
    # $ADObjectName is the sAMAccountName of an object. 
    $ADObject = Get-ADObject -LDAPFilter "(sAMAccountName=$ADObjectName)" -Server $Server 
If ($ADObject -eq $Null) 
    "Object $ADObjectName not found" 
# Prompt for the attribute LDAPDisplayName. 
$AttrName = Read-Host "Enter the LDAPDisplayName of the attribute to be fixed" 
# Prompt for output file from repadmin. 
$File = Read-Host "Enter file containing output from repadmin command" 
# Retrieve the contents of the file. 
$RepAdm = Get-Content $File 
$k = 0 
$Count = 0 
$Total = 0 
# Array of attribute values. 
$LegacyValues = @() 
ForEach ($Line In $RepAdm) 
    $k = $k + 1 
    If ($Line.Length -ge 6) 
        # Find lines identifying "Legacy" values of the object. 
        # These values cannot take advantage of LVR. 
        If ($Line.Substring(06) -eq "LEGACY") 
            # Parse this line for the attribute lDAPDisplayName. 
            $Attr = $Line.Substring(7).Trim() 
            # Only deal with the specified attribute. 
            If ($Attr.ToLower() -eq $AttrName.ToLower()) 
                # Add the value on the next line to the array. 
                $Value = $RepAdm[$k + 1].Trim() 
                $LegacyValues = $LegacyValues + $Value 
                $Count = $Count + 1 
                $Total = $Total + 1 
                # Process no more than 4000 values at a time. 
                If ($Count -eq 4000) 
                    # Remove all legacy values from the attribute of the object. 
                    Set-ADObject -Identity $ADObject.distinguishedName ` 
                        -Remove @{$AttrName=$LegacyValues} -Server $Server 
                    Start-Sleep -Seconds 10 
                    # Add the values back into the object attribute. 
                    Set-ADObject -Identity $ADObject.distinguishedName ` 
                        -Add @{$AttrName=$LegacyValues} -Server $Server 
                    # Initialize the array and the counter. 
                    $LegacyValues = @() 
                    $Count = 0 
                    Start-Sleep -Seconds 10 
# Process any remaining values. 
If ($Count -gt 0{ 
    # Remove all legacy values from the attribute of the object. 
    Set-ADObject -Identity $ADObject.distinguishedName -Remove @{$AttrName=$LegacyValues} ` 
        -Server $Server 
    Start-Sleep -Seconds 10 
    # Add the values back into the object attribute. 
    Set-ADObject -Identity $ADObject.distinguishedName -Add @{$AttrName=$LegacyValues} ` 
        -Server $Server 
"$Total values of attribute $AttrName of $ADObjectName fixed"