AD Loopback: Merge and Replace
AD Loopback: Merge and Replace
A user’s usual desktop policy follows the user object’s OU. A shared terminal or remote desktop server may instead need user settings selected by the computer’s location. Linking a GPO containing user settings to a computer OU does not, on its own, make those settings apply to every person signing in there. Loopback supplies that different policy selection.
Merge and Replace can produce the same value for a conflicting setting. To distinguish them, include a setting that exists only at the user location: Merge keeps it, whereas Replace uses the computer-location list instead.
The recorded lab used corp.test.checo.cc, NetBIOS ADLAB, LAB-DC1, and LAB-MEMBER. Both machines were Windows Server 2022 Datacenter; the member reported 10.0.20348, and Windows PowerShell was 5.1.20348.5386. The same ordinary ADLAB\KB03-User completed three real console logons on the same member server. Each mode change was followed by computer-policy refresh and a server restart to obtain a fresh logon.
1. Loopback policy selection
Ordinarily, the computer object selects computer policy and the user object selects user policy. The loopback setting is a computer policy, but its result is still user configuration from GPOs. It does not convert HKLM settings into HKCU settings.
Merge gathers the ordinary user list, then appends the computer-location list. For ordinary conflicts, the latter user settings have precedence. Replace does not gather the user-location list. The user object stays in its OU and the account identity is unchanged; the selected policy list changes. Links, inheritance, filtering, and enabled user/computer sections still matter. Microsoft describes the two list-building modes in Loopback processing.
The member’s own C:\Windows\PolicyDefinitions\GroupPolicy.admx identified the setting:
class="Machine"
key="Software\Policies\Microsoft\Windows\System"
valueName="UserPolicyMode"
UserPolicyMode_Merge: decimal value="1"
UserPolicyMode_Replace: decimal value="2"The key is HKLM\Software\Policies\Microsoft\Windows\System\UserPolicyMode. The historical off control wrote 0, Merge wrote 1, and Replace wrote 2. That records this experiment’s input, not a general recommendation to substitute a hand-written zero for the administrative template’s Disabled/Not Configured state. Final rollback removed the experimental policy and the value was absent again.
2. Compare policy markers
OU=KB-Lab-20261009
OU=Loopback03-Users
KB03-User
link: KB03-UserLocation
OU=Loopback03-Computers
LAB-MEMBER
links: KB03-ComputerLocation, KB03-LoopbackModeThe user-location GPO set Conflict=UserOU and UserOnly=Present. The computer-location GPO’s user configuration set Conflict=ComputerOU and ComputerOnly=Present. All three values were under HKCU\Software\Policies\KB03Loopback. A separate GPO controlled the loopback mode, so the switch was the only changing input.
| Mode | Experimental GPOs in user gpresult | Conflict | UserOnly | ComputerOnly |
|---|---|---|---|---|
| Off control, 0 | UserLocation | UserOU | Present | Absent |
| Merge, 1 | ComputerLocation and UserLocation | ComputerOU | Present | Present |
| Replace, 2 | ComputerLocation | ComputerOU | Absent | Present |
| Remove links and refresh | N/A | Absent | Absent | Absent |
The Merge report listed ComputerLocation first; that display order is not an execution trace. Actual HKCU values establish the winner. Both active modes returned ComputerOU, but only Merge retained UserOnly.
The recorded Merge result was:
RSOP data for ADLAB\KB03-User on LAB-MEMBER : Logging Mode
Applied Group Policy Objects
-----------------------------
KB03-ComputerLocation
KB03-UserLocation
Conflict=ComputerOU
UserOnly=Present
ComputerOnly=PresentReplace then returned:
RSOP data for ADLAB\KB03-User on LAB-MEMBER : Logging Mode
Applied Group Policy Objects
-----------------------------
KB03-ComputerLocation
Conflict=ComputerOU
UserOnly=<absent>
ComputerOnly=Presentwhoami /user retained the same user SID. Group output included INTERACTIVE, CONSOLE LOGON, and Medium Mandatory Level. The observer ran in the ordinary logged-on user’s token, so HKCU represented that person. DC configuration and member computer-policy operations used SYSTEM separately.
3. Configure loopback
In GPMC, edit the GPO linked on the target computer’s path: Computer Configuration → Policies → Administrative Templates → System → Group Policy → Configure user Group Policy loopback processing mode. Enable it and choose Merge or Replace. Put the terminal-specific user settings in GPOs reachable through the computer location.
Merge is suitable when the normal user settings should remain except where terminal policy overrides them. Replace removes the user-location policy list from this processing pass. Before switching, inspect user-location drive mapping, folder redirection, and other settings that would leave scope.
The following example assumes the dedicated OUs, test user, and three named GPOs already exist. Run it in elevated PowerShell on LAB-DC1, with the ActiveDirectory and GroupPolicy modules and permissions for those objects. Save the original computer DN, both sets of links, and GPO contents before changing anything:
Import-Module ActiveDirectory
Import-Module GroupPolicy
$dc = 'LAB-DC1.corp.test.checo.cc'
$domain = 'corp.test.checo.cc'
$root = 'OU=KB-Lab-20261009,DC=corp,DC=test,DC=checo,DC=cc'
$userOU = 'OU=Loopback03-Users,' + $root
$computerOU = 'OU=Loopback03-Computers,' + $root
$userGPO = Get-GPO -Name 'KB03-UserLocation' -Domain $domain -Server $dc
$computerGPO = Get-GPO -Name 'KB03-ComputerLocation' -Domain $domain -Server $dc
$modeGPO = Get-GPO -Name 'KB03-LoopbackMode' -Domain $domain -Server $dc
$computer = Get-ADComputer -Identity 'LAB-MEMBER' -Server $dc
$backup = 'C:\KB-Loopback-03\operator-backup'
New-Item -ItemType Directory -Path $backup -Force | Out-Null
$computer | Export-Clixml ($backup + '\computer-before.xml')
Get-GPInheritance -Target $userOU -Domain $domain -Server $dc | Export-Clixml ($backup + '\user-links.xml')
Get-GPInheritance -Target $computerOU -Domain $domain -Server $dc | Export-Clixml ($backup + '\computer-links.xml')
foreach ($g in @($userGPO, $computerGPO, $modeGPO)) {
Backup-GPO -Guid $g.Id -Path $backup -Domain $domain -Server $dc | Out-Null
}Keep these variables for the following blocks. Write harmless markers, establish only the missing links, and move the computer into the dedicated computer OU:
$key = 'HKCU\Software\Policies\KB03Loopback'
Set-GPRegistryValue -Guid $userGPO.Id -Key $key -ValueName Conflict -Type String -Value UserOU -Domain $domain -Server $dc | Out-Null
Set-GPRegistryValue -Guid $userGPO.Id -Key $key -ValueName UserOnly -Type String -Value Present -Domain $domain -Server $dc | Out-Null
Set-GPRegistryValue -Guid $computerGPO.Id -Key $key -ValueName Conflict -Type String -Value ComputerOU -Domain $domain -Server $dc | Out-Null
Set-GPRegistryValue -Guid $computerGPO.Id -Key $key -ValueName ComputerOnly -Type String -Value Present -Domain $domain -Server $dc | Out-Null
New-GPLink -Guid $userGPO.Id -Target $userOU -Domain $domain -Server $dc | Out-Null
New-GPLink -Guid $computerGPO.Id -Target $computerOU -Domain $domain -Server $dc | Out-Null
New-GPLink -Guid $modeGPO.Id -Target $computerOU -Domain $domain -Server $dc | Out-Null
Move-ADObject -Identity $computer.ObjectGUID -TargetPath $computerOU -Server $dcDo not repeat New-GPLink for links already present. This block selects Merge; the historical control used 0 and the Replace test used 2. Back up before every change:
Backup-GPO -Guid $modeGPO.Id -Path $backup -Domain $domain -Server $dc | Out-Null
Set-GPRegistryValue -Guid $modeGPO.Id -Key 'HKLM\Software\Policies\Microsoft\Windows\System' -ValueName UserPolicyMode -Type DWord -Value 1 -Domain $domain -Server $dc | Out-Null
Get-GPRegistryValue -Guid $modeGPO.Id -Key 'HKLM\Software\Policies\Microsoft\Windows\System' -ValueName UserPolicyMode -Domain $domain -Server $dcOn the member, refresh computer policy and read the effective mode in an elevated local session. The recorded experiment restarted the server between modes; that ends its active sessions:
gpupdate /target:computer /force /wait:120
if ($LASTEXITCODE -ne 0) { throw 'Computer gpupdate failed' }
Get-ItemPropertyValue -Path 'HKLM:\Software\Policies\Microsoft\Windows\System' -Name UserPolicyMode
Restart-Computer -ForceAfter signing in as the test user, use that user’s ordinary PowerShell window, not SYSTEM or another administrator, to collect identity, user RSoP, and actual values:
whoami /user
whoami /groups
gpupdate /target:user /force /wait:120
if ($LASTEXITCODE -ne 0) { throw 'User gpupdate failed' }
gpresult /scope user /r
if ($LASTEXITCODE -ne 0) { throw 'User gpresult failed' }
$k='HKCU:\Software\Policies\KB03Loopback'
foreach($n in @('Conflict','UserOnly','ComputerOnly')){$v=if(Test-Path $k){(Get-Item $k).GetValue($n)}else{$null};if($null -eq $v){$v='<absent>'};"$n=$v"}GetValue makes missing values explicit as <absent>. In Windows PowerShell 5.1, a missing property queried through Get-ItemPropertyValue can interrupt the script; a stopped observer is not evidence that all markers were removed.
4. Diagnose results
If computer-location user settings never arrive, first inspect the effective UserPolicyMode. If it is missing, check the mode GPO’s computer section, computer DN/link path, and computer Read/Apply permissions before rearranging user-OU links.
If the mode is 1 or 2 but the expected user GPO is missing, inspect its user section, user Read/Apply rights, and the computer’s ability to retrieve the GPO. Removing Authenticated Users can remove the computer’s read path as well. Inspect WMI filtering, the policy server, and GroupPolicy Operational logs. A GPO containing only computer settings need not appear as an applied user-settings GPO.
If Merge and Replace appear identical, add a user-location-only marker. Looking only at the conflict hides their intended difference. Preferences also need their own cleanup settings checked: a persistent old value is not proof that its original GPO remains in the active list.
5. Restore the baseline
Move the computer to its saved parent and remove the three dedicated links. Keep the test user available until the same user can refresh and verify cleanup:
$before = Import-Clixml ($backup + '\computer-before.xml')
$parent = $before.DistinguishedName.Substring($before.DistinguishedName.IndexOf(',') + 1)
Move-ADObject -Identity $before.ObjectGUID -TargetPath $parent -Server $dc
Remove-GPLink -Guid $userGPO.Id -Target $userOU -Domain $domain -Server $dc
Remove-GPLink -Guid $computerGPO.Id -Target $computerOU -Domain $domain -Server $dc
Remove-GPLink -Guid $modeGPO.Id -Target $computerOU -Domain $domain -Server $dc
Get-ADComputer -Identity $before.ObjectGUID -Server $dc | Select-Object DistinguishedNameRefresh computer policy in the elevated member session, then rerun the user observer in the real test-user session. The recorded computer returned to CN=LAB-MEMBER,CN=Computers,DC=corp,DC=test,DC=checo,DC=cc, and the user result was:
Applied Group Policy Objects
-----------------------------
N/A
Conflict=<absent>
UserOnly=<absent>
ComputerOnly=<absent>The machine loopback value also became absent. For changes to an existing GPO, restore its recorded backup and links rather than deleting it. These three GPOs, the user, and empty lab OUs were disposable; only their recorded GUIDs were removed after verification. The user was logged off, temporary interactive tasks were removed, and automatic-logon values were restored to their original existence, type, and value. The member secure-channel check returned True; existing OU links and original GPO inventory/modification times remained unchanged.
