<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suat Can Geyik</title>
    <description>The latest articles on DEV Community by Suat Can Geyik (@scg).</description>
    <link>https://dev.to/scg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3918769%2F8784df05-707e-4873-83e4-924233420f69.jpg</url>
      <title>DEV Community: Suat Can Geyik</title>
      <link>https://dev.to/scg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scg"/>
    <language>en</language>
    <item>
      <title>AD DS Schema — Safe Extension Lab</title>
      <dc:creator>Suat Can Geyik</dc:creator>
      <pubDate>Fri, 30 Oct 2026 01:03:47 +0000</pubDate>
      <link>https://dev.to/scg/ad-ds-schema-safe-extension-lab-4ncc</link>
      <guid>https://dev.to/scg/ad-ds-schema-safe-extension-lab-4ncc</guid>
      <description>&lt;p&gt;Changing the Active Directory schema is one of the few things in AD you can't undo. You can't delete what you add. Rolling back means restoring every domain controller in the forest. That's why most admins never touch it, and why the ones who do are careful.&lt;/p&gt;

&lt;p&gt;I wanted to understand it properly, so I did it in my own lab: one custom attribute, one auxiliary class, linked to the &lt;code&gt;user&lt;/code&gt; class, replicated to the second DC, then a deactivation drill. It follows the Contoso in-house app scenario in Unit 6 of the Microsoft Learn module &lt;a href="https://learn.microsoft.com/en-us/training/modules/manage-active-directory-domain-services-flexible-single-master-operation-roles/" rel="noopener noreferrer"&gt;Manage AD DS domain controllers and FSMO roles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It didn't go to plan, which is why this post is worth reading. The very first health check found that one DC hadn't received changes from the Schema Master for three days. After I fixed that, I made four small mistakes during the extension itself. They're all here, with the error and the fix, because those are the parts that will save you time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you'd ever extend the schema
&lt;/h2&gt;

&lt;p&gt;The schema is the rulebook for the whole forest. It defines which object types exist (classes) and which properties they can hold (attributes). Out of the box, a user has fields like &lt;code&gt;givenName&lt;/code&gt;, &lt;code&gt;mail&lt;/code&gt; and &lt;code&gt;department&lt;/code&gt;. If an application needs to store something AD doesn't know about, the schema has to learn it first.&lt;/p&gt;

&lt;p&gt;You'll meet this in real life when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An in-house app&lt;/strong&gt; needs its own field on user accounts, like the badge ID in this lab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exchange&lt;/strong&gt; runs &lt;code&gt;/PrepareSchema&lt;/code&gt; before installation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows LAPS&lt;/strong&gt; runs &lt;code&gt;Update-LapsADSchema&lt;/code&gt; to store local admin passwords on computer objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Manager&lt;/strong&gt; runs &lt;code&gt;extadsch.exe&lt;/code&gt; so clients can find their site in AD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those vendor tools do exactly what this lab does by hand, just with their own registered OIDs. Doing it once yourself makes those installs a lot less mysterious, and it gives you something concrete to talk about in an interview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal and environment
&lt;/h2&gt;

&lt;p&gt;In about 60 minutes you will extend the forest schema with one custom attribute, watch it replicate to DC02, and learn why schema changes are treated as permanent. This mirrors Contoso's in-house app scenario from Unit 6.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value in this lab&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DC01&lt;/td&gt;
&lt;td&gt;Windows Server 2022, Azure VM, assumed Schema Master&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC02&lt;/td&gt;
&lt;td&gt;Second DC, Hyper-V VM inside the Azure lab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account&lt;/td&gt;
&lt;td&gt;Your lab domain admin (forest root domain)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test user&lt;/td&gt;
&lt;td&gt;Any lab user, called &lt;code&gt;testuser&lt;/code&gt; below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Naming prefix&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;lab-&lt;/code&gt; / &lt;code&gt;lab&lt;/code&gt; so every test object is easy to spot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both DCs healthy and replicating (checked in Task 1)&lt;/li&gt;
&lt;li&gt;Run everything on DC01 from an elevated PowerShell unless a step says otherwise&lt;/li&gt;
&lt;li&gt;Take an Azure snapshot of DC01 and a Hyper-V checkpoint of DC02 before Task 3, as a last resort only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Safety:&lt;/strong&gt; schema changes replicate to the whole forest within minutes and cannot be deleted. Rolling back means restoring every DC, which is why real companies test in a separate lab forest first. Use only the &lt;code&gt;lab-&lt;/code&gt; names in this guide.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How to read this post:&lt;/strong&gt; each task has two parts. First the &lt;strong&gt;steps&lt;/strong&gt;, written so you can follow them in your own lab. Then my &lt;strong&gt;exercise notes&lt;/strong&gt;: what actually happened when I ran them, including the errors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Task 1 — Baseline: Schema Master, version, replication health
&lt;/h2&gt;

&lt;p&gt;Before you change something that can't be undone, you need to know the starting point. Three questions: which DC can accept the change, what version the schema is at now, and whether the change will actually reach every DC.&lt;/p&gt;

&lt;p&gt;Record these values before changing anything; they are your "before" screenshot for the blog post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Who holds the Schema Master role?&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ADForest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SchemaMaster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ForestMode&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;netdom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fsmo&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Schema version on each DC (expect 88 for Server 2019/2022)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADRootDSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schemaNamingContext&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;objectVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;objectVersion&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;objectVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;objectVersion&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Replication must be clean before a schema change&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/replsummary&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/showrepl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result: both DCs report the same &lt;code&gt;objectVersion&lt;/code&gt;, and &lt;code&gt;/replsummary&lt;/code&gt; shows 0 failures. If DC02 shows errors, fix replication first. A schema change on a broken topology is a classic real-world outage.&lt;/p&gt;

&lt;p&gt;If the Schema Master is not DC01, run the later tasks on whichever DC holds it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 1 exercise notes: DC02 → DC01 replication failure (error 8524), 27 Oct 2026
&lt;/h3&gt;

&lt;p&gt;I expected this step to take two minutes. It found two surprises.&lt;/p&gt;

&lt;p&gt;The first was that &lt;strong&gt;DC01 wasn't the Schema Master&lt;/strong&gt;. I'd moved the role to DC02 earlier while troubleshooting a failed FSMO transfer (that's &lt;a href="https://dev.toLINK%20TO%20FSMO%20POST"&gt;a separate post&lt;/a&gt;), and the guide still assumed DC01.&lt;/p&gt;

&lt;p&gt;The second was a &lt;strong&gt;replication failure&lt;/strong&gt; in exactly the direction that mattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; the baseline check found that DC01 had not received changes from DC02, the Schema Master, since 24 Oct. It was fixed by forcing a pull once DNS resolved correctly. Both DCs ended with 0 failures, so it is now safe to continue with Task 3.&lt;/p&gt;

&lt;h4&gt;
  
  
  Baseline values recorded
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forest / mode&lt;/td&gt;
&lt;td&gt;lab.local / Windows2016Forest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema Master&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;DC02&lt;/strong&gt; (not DC01 as the guide assumed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain naming, PDC, RID, Infrastructure&lt;/td&gt;
&lt;td&gt;DC01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema objectVersion&lt;/td&gt;
&lt;td&gt;88 on DC01 and DC02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC01 IPs&lt;/td&gt;
&lt;td&gt;10.0.0.4 (Azure NIC), 192.168.10.1 (vEthernet LabNetwork)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC02 IP&lt;/td&gt;
&lt;td&gt;192.168.10.10 (nested Hyper-V VM)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Symptom
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repadmin /replsummary
Source DSA     largest delta     fails/total  error
 DC01          20m:45s           0 / 5
 DC02          05d.21h:29m:27s   2 / 5        (8524) DNS lookup failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Direction that failed: &lt;strong&gt;DC01 pulling from DC02&lt;/strong&gt;. DC02 pulling from DC01 was healthy. With DC02 as Schema Master, any schema change would never have reached DC01.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why this would have hurt:&lt;/strong&gt; if I'd skipped the baseline and gone straight to Task 3, the new attribute would have been created on DC02 and simply never arrived on DC01. Nothing would have warned me. I'd have been debugging the attribute when the real problem was replication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Investigation
&lt;/h4&gt;

&lt;p&gt;Error 8524 says "DNS lookup failure", so I started with DNS, then checked ports, then the per-partition status.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DNS servers per DC&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ipconfig /all | findstr /i "IPv4 DNS"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DC01 points only to itself on both adapters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC02 host record&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Resolve-DnsName DC02.lab.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;192.168.10.10 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC02 replication CNAME&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Resolve-DnsName "&amp;lt;DC02 NTDS GUID&amp;gt;._msdcs.lab.local"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;→ dc02.lab.local → 192.168.10.10 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS health, DC01&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dcdiag /test:dns /s:DC01 /v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Passed; warning: dynamic IP on Azure NIC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS health, DC02&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dcdiag /test:dns /s:DC02 /v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All PASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ports DC01 → DC02&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Test-NetConnection 192.168.10.10 -Port 135&lt;/code&gt; / &lt;code&gt;389&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;True / True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ports DC02 → DC01&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Test-NetConnection 10.0.0.4 -Port 389&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DC02 network profile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-NetConnectionProfile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DomainAuthenticated ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-partition status&lt;/td&gt;
&lt;td&gt;&lt;code&gt;repadmin /showrepl DC01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only ForestDnsZones still failing; last success 2026-10-24 08:35&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything passed, yet the error was still there. That meant either DNS had been broken earlier and recovered, or I was checking the wrong name. So I checked the name replication actually uses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key check: how DC01 finds DC02 for replication (the GUID CNAME)
&lt;/h4&gt;

&lt;p&gt;Replication does not look up &lt;code&gt;DC02.lab.local&lt;/code&gt; directly. It looks up DC02 by its &lt;strong&gt;DSA GUID&lt;/strong&gt;, so DC01 can resolve DC02's host name and still fail with 8524.&lt;/p&gt;

&lt;p&gt;The lookup chain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each DC has an &lt;strong&gt;NTDS Settings&lt;/strong&gt; object in AD. Its &lt;code&gt;objectGUID&lt;/code&gt; is the DC's DSA GUID, the same value &lt;code&gt;repadmin /showrepl&lt;/code&gt; prints as "DSA object GUID".&lt;/li&gt;
&lt;li&gt;Netlogon on each DC registers a CNAME in DNS: &lt;code&gt;&amp;lt;DSA GUID&amp;gt;._msdcs.&amp;lt;forest root&amp;gt;&lt;/code&gt; → the DC's host name.&lt;/li&gt;
&lt;li&gt;The replicating DC resolves that CNAME, then the host (A) record, then connects over RPC.&lt;/li&gt;
&lt;li&gt;If step 2 or 3 fails, the result is &lt;strong&gt;8524&lt;/strong&gt;: "DSA operation is unable to proceed because of a DNS lookup failure".
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Find the DN of DC02's NTDS Settings object&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$ntds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADDomainController&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NTDSSettingsObjectDN&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 2. Read its objectGUID = DC02's DSA GUID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$guid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ntds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;objectGUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectGUID&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 3. Resolve the exact name replication uses&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Resolve-DnsName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$guid&lt;/span&gt;&lt;span class="s2"&gt;._msdcs.lab.local"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output on DC01:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name                                                Type   TTL  Section  NameHost
----                                                ----   ---  -------  --------
3747608c-0a43-46b9-883d-aa90e8672f5d._msdcs.lab.local CNAME  600  Answer   dc02.lab.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to read it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The GUID &lt;code&gt;3747608c-0a43-46b9-883d-aa90e8672f5d&lt;/code&gt; matches "DSA object GUID" for DC02 in &lt;code&gt;repadmin /showrepl DC01&lt;/code&gt;, so it's the right record.&lt;/li&gt;
&lt;li&gt;CNAME → &lt;code&gt;dc02.lab.local&lt;/code&gt; → A record 192.168.10.10, so the full chain resolves. DNS was not failing at check time.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;_msdcs.lab.local&lt;/code&gt; zone is normally stored in the &lt;strong&gt;ForestDnsZones&lt;/strong&gt; partition, the same partition that kept failing. The records DC01 needed and the replication that delivers them depended on each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the CNAME were missing, the fix on DC02 would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;nltest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/dsregdns&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;# re-register DC DNS records&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Restart-Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Netlogon&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check DNS Manager on DC01 → &lt;code&gt;_msdcs.lab.local&lt;/code&gt; for the GUID record, and run &lt;code&gt;Resolve-DnsName&lt;/code&gt; again.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cause
&lt;/h4&gt;

&lt;p&gt;When the failures happened, DC01 could not resolve DC02's replication name (&lt;code&gt;&amp;lt;GUID&amp;gt;._msdcs.lab.local&lt;/code&gt;). By the time of the check, DNS resolved correctly, but the failure stayed in the report because no new pull had run for ForestDnsZones. Likely trigger: DC02's DNS records only reach DC01 through replication from DC02, which was the broken link (a DNS "island" loop).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In plain words:&lt;/strong&gt; DC01 needed DC02's address to replicate from DC02, but that address only arrives on DC01 &lt;em&gt;by&lt;/em&gt; replicating from DC02. Once that loop breaks, it can stay broken until you force a fresh attempt, even after the underlying DNS is fine again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Fix
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Confirmed DNS and ports were healthy (investigation table above).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Forced a pull of each partition from DC02 into DC01:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/replicate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CN=Schema,CN=Configuration,DC=lab,DC=local"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/replicate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DC=ForestDnsZones,DC=lab,DC=local"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/syncall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/Ade&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c"&gt;# pull into DC01; no /P&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/replsummary&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Final result
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repadmin /replsummary   (2026-10-27 21:09)
Source DSA     largest delta   fails/total
 DC01          14m:06s         0 / 5
 DC02          :17s            0 / 5
Destination DSA
 DC01          :17s            0 / 5
 DC02          14m:06s         0 / 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Lessons learned
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Always run Task 1 before a schema change. Replication from the &lt;strong&gt;Schema Master&lt;/strong&gt; must be clean.&lt;/li&gt;
&lt;li&gt;Read &lt;code&gt;/replsummary&lt;/code&gt; by direction: the row shows which DC can't pull from which.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;repadmin /showrepl &amp;lt;DC&amp;gt;&lt;/code&gt; shows the failing &lt;strong&gt;partition&lt;/strong&gt; and its last success time; &lt;code&gt;/replsummary&lt;/code&gt; alone hides that.&lt;/li&gt;
&lt;li&gt;An error in &lt;code&gt;/replsummary&lt;/code&gt; can be &lt;strong&gt;old&lt;/strong&gt;. Fix the cause, then force a new attempt before trusting the result.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;repadmin /syncall &amp;lt;DC&amp;gt; /AdeP&lt;/code&gt; &lt;strong&gt;pushes&lt;/strong&gt; out from that DC. Without &lt;code&gt;/P&lt;/code&gt;, it &lt;strong&gt;pulls&lt;/strong&gt; into it. Pick based on which DC is behind.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Restart-Service NlaSvc -Force&lt;/code&gt; fails on Server 2022 (dependent service netprofm). It's harmless; reboot instead if the network profile is wrong.&lt;/li&gt;
&lt;li&gt;Find the real Schema Master first (&lt;code&gt;netdom query fsmo&lt;/code&gt;) and aim &lt;code&gt;ldifde -s&lt;/code&gt; at it. In this lab that was &lt;strong&gt;DC02&lt;/strong&gt; on 27 Oct.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Follow-ups for the lab environment
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;☐ DC01 is on two networks and registers both IPs in DNS. Decide which IP DCs should use.&lt;/li&gt;
&lt;li&gt;☐ Set DC01's Azure NIC private IP to Static in the Azure portal (fixes the dcdiag dynamic-IP warning).&lt;/li&gt;
&lt;li&gt;☐ DNS client order on each DC: partner DC first, 127.0.0.1 second.&lt;/li&gt;
&lt;li&gt;☐ Update Tasks 3–5 to use &lt;code&gt;-s DC02&lt;/code&gt;. &lt;em&gt;(Superseded on 28 Oct: the Schema Master moved back to DC01, so the tasks below target DC01.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Task 2 — Tools and temporary Schema Admins access
&lt;/h2&gt;

&lt;p&gt;Schema Admins is one of the most powerful groups in AD: its members can change the rules for the whole forest. So the habit is to keep it empty and only join it for the change window, like taking a key out of a safe and putting it back.&lt;/p&gt;

&lt;p&gt;Best practice is to keep Schema Admins empty and add yourself only for the change window. You remove the membership again in Task 5.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register the hidden Schema snap-in: &lt;code&gt;regsvr32 schmmgmt.dll&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;mmc&lt;/code&gt;, then File → Add/Remove Snap-in → &lt;strong&gt;Active Directory Schema&lt;/strong&gt;. Save it as &lt;code&gt;Schema.msc&lt;/code&gt; on the desktop.&lt;/li&gt;
&lt;li&gt;Add your account to the group:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Add-ADGroupMember -Identity "Schema Admins" -Members "&amp;lt;your admin account&amp;gt;"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sign out and back in, because group membership only lands in a new logon token.&lt;/li&gt;
&lt;li&gt;Verify: &lt;code&gt;whoami /groups | findstr /i schema&lt;/code&gt; should list &lt;code&gt;Schema Admins&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Interview point: membership alone is not enough. The change must also be written on the Schema Master, and the snap-in connects there automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 3 — Create the attribute and an auxiliary class (LDIF)
&lt;/h2&gt;

&lt;p&gt;This is the actual change. Two new schema objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;strong&gt;attribute&lt;/strong&gt;, &lt;code&gt;labEmployeeBadgeID&lt;/code&gt;: the new field, a short text value&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;auxiliary class&lt;/strong&gt;, &lt;code&gt;labUserExtension&lt;/code&gt;: a small add-on that carries the attribute and can be attached to an existing class later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one needs a globally unique ID (an OID), the same way every built-in attribute has one.&lt;/p&gt;

&lt;p&gt;Every schema object needs a globally unique OID. Real vendors register their own; for a lab, generate one under Microsoft's private branch with this well-known script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$Prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2.840.113556.1.8000.2554"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.Guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UInt64&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$GUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowHexSpecifier"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$BaseOID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{0}.{1}.{2}.{3}.{4}.{5}.{6}.{7}"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$BaseOID&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c"&gt;# save this value in your lab notes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$BaseOID&lt;/code&gt; is your own private OID "root", for example &lt;code&gt;1.2.840.113556.1.8000.2554.41250.12011.17862.38207.53142.1458291.7712345&lt;/code&gt;. You never use it alone. You hang numbered branches under it, like folders:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OID&lt;/th&gt;
&lt;th&gt;Used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;branch for attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;first attribute: &lt;code&gt;labEmployeeBadgeID&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.1.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;second attribute: &lt;code&gt;lab-TestDefunct&lt;/code&gt; (Task 5 drill)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;branch for classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.2.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;first class: &lt;code&gt;labUserExtension&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run the next steps in the &lt;strong&gt;same PowerShell window&lt;/strong&gt; where you generated &lt;code&gt;$BaseOID&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1. Save the base OID.&lt;/strong&gt; The variable is lost when the window closes, and you need the same base for every future lab object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$BaseOID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\BaseOID.txt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ascii&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# In a later session, load it back instead of generating a new one:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# $BaseOID = (Get-Content C:\Lab\BaseOID.txt).Trim()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2. Build the two OIDs.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$AttrOID&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BaseOID&lt;/span&gt;&lt;span class="s2"&gt;.1.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$ClassOID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BaseOID&lt;/span&gt;&lt;span class="s2"&gt;.2.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$AttrOID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$ClassOID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3. Write the LDF with the OIDs already filled in.&lt;/strong&gt; The double-quoted here-string replaces &lt;code&gt;$AttrOID&lt;/code&gt; and &lt;code&gt;$ClassOID&lt;/code&gt; with their values, so there is no manual editing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sh"&gt;@"
dn: CN=lab-EmployeeBadgeID,DC=X
changetype: add
objectClass: attributeSchema
lDAPDisplayName: labEmployeeBadgeID
adminDisplayName: lab-EmployeeBadgeID
adminDescription: Lab test attribute - employee badge ID
attributeID: &lt;/span&gt;&lt;span class="nv"&gt;$AttrOID&lt;/span&gt;&lt;span class="sh"&gt;
attributeSyntax: 2.5.5.12
oMSyntax: 64
isSingleValued: TRUE
rangeUpper: 32
searchFlags: 0

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-

dn: CN=lab-UserExtension,DC=X
changetype: add
objectClass: classSchema
lDAPDisplayName: labUserExtension
adminDisplayName: lab-UserExtension
adminDescription: Lab auxiliary class for user objects
governsID: &lt;/span&gt;&lt;span class="nv"&gt;$ClassOID&lt;/span&gt;&lt;span class="sh"&gt;
objectClassCategory: 3
subClassOf: top
mayContain: labEmployeeBadgeID

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-

"@&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-lab.ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ascii&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4. Check the file before importing.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-lab.ldf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Select-String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-lab.ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Pattern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attributeID|governsID"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both lines must show your full OIDs ending in &lt;code&gt;.1.1&lt;/code&gt; and &lt;code&gt;.2.1&lt;/code&gt;. If either shows an empty value, &lt;code&gt;$BaseOID&lt;/code&gt; was not set in this window. Load it from &lt;code&gt;BaseOID.txt&lt;/code&gt; and repeat Steps 2–3.&lt;/p&gt;

&lt;p&gt;For reference, the file you just generated looks like this, with &lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt; replaced by your value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: CN=lab-EmployeeBadgeID,DC=X
changetype: add
objectClass: attributeSchema
lDAPDisplayName: labEmployeeBadgeID
adminDisplayName: lab-EmployeeBadgeID
adminDescription: Lab test attribute - employee badge ID
attributeID: &amp;lt;BASE&amp;gt;.1.1
attributeSyntax: 2.5.5.12
oMSyntax: 64
isSingleValued: TRUE
rangeUpper: 32
searchFlags: 0

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-

dn: CN=lab-UserExtension,DC=X
changetype: add
objectClass: classSchema
lDAPDisplayName: labUserExtension
adminDisplayName: lab-UserExtension
adminDescription: Lab auxiliary class for user objects
governsID: &amp;lt;BASE&amp;gt;.2.1
objectClassCategory: 3
subClassOf: top
mayContain: labEmployeeBadgeID

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import it on the Schema Master. &lt;code&gt;-c&lt;/code&gt; swaps the &lt;code&gt;DC=X&lt;/code&gt; placeholder for your real schema partition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 5. Import on the current Schema Master (DC01 since 28 Oct; check with: netdom query fsmo)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ldifde&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-lab.ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DC=X"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#schemaNamingContext"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What the key lines mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;attributeSyntax 2.5.5.12&lt;/code&gt; + &lt;code&gt;oMSyntax 64&lt;/code&gt; = Unicode string, capped at 32 characters by &lt;code&gt;rangeUpper&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;objectClassCategory: 3&lt;/code&gt; = auxiliary class (1 = structural, 2 = abstract)&lt;/li&gt;
&lt;li&gt;the empty &lt;code&gt;dn:&lt;/code&gt; blocks write &lt;code&gt;schemaUpdateNow&lt;/code&gt; to RootDSE, so the next entry sees the new attribute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the result in the Schema snap-in under Attributes and Classes. Don't use &lt;code&gt;-k&lt;/code&gt;, since a silent failure is exactly what you want to see in a lab.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 4 — Link the class to user, refresh the schema, use the attribute
&lt;/h2&gt;

&lt;p&gt;Creating the attribute isn't enough on its own: no object can use it yet. Instead of redefining the built-in &lt;code&gt;user&lt;/code&gt; class, you attach the auxiliary class to it. Every user then gains the new field, and nothing Microsoft shipped gets changed.&lt;/p&gt;

&lt;p&gt;This is the Unit 6 pattern: the structural class &lt;code&gt;user&lt;/code&gt; gains new attributes through an auxiliary class, without being redefined. Save as &lt;code&gt;C:\Lab\schema-link.ldf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: CN=User,DC=X
changetype: modify
add: auxiliaryClass
auxiliaryClass: labUserExtension
-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ldifde&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-link.ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DC=X"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#schemaNamingContext"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Force a schema reload the way the unit shows (the knowledge-check answer):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;adsiedit.msc&lt;/code&gt;, then Connect to → &lt;strong&gt;Schema&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Right-click the Schema container → &lt;strong&gt;Update Schema Now&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open a &lt;strong&gt;new&lt;/strong&gt; PowerShell window (the AD module caches the schema per session), then write and read the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Set-ADUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;testuser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-Replace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B-1001"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ADUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;testuser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# LDAP filter view, the way an application would query it&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ADUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LDAPFilter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(labEmployeeBadgeID=B-*)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In ADUC, turn on View → Advanced Features and open testuser → &lt;strong&gt;Attribute Editor&lt;/strong&gt;. &lt;code&gt;labEmployeeBadgeID&lt;/code&gt; now shows next to built-in attributes like &lt;code&gt;givenName&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Try one invalid write too: a 40-character value should be rejected because of &lt;code&gt;rangeUpper: 32&lt;/code&gt;. That is the schema enforcing data integrity, the point of the whole unit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 5 — Verify on DC02, practise deactivation, clean up
&lt;/h2&gt;

&lt;p&gt;The change was made on one DC. It's only finished when every DC has it, and when the temporary access from Task 2 is gone again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replication check.&lt;/strong&gt; The change started on the Schema Master and must now exist on DC02:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/syncall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/AdeP&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADRootDSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schemaNamingContext&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SearchBase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lDAPDisplayName -eq 'labEmployeeBadgeID'"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ADUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;testuser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;objectVersion&lt;/code&gt; from Task 1 does not change. It tracks only Microsoft's &lt;code&gt;adprep&lt;/code&gt; updates, not custom extensions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why you can't simply remove it.&lt;/strong&gt; &lt;code&gt;labEmployeeBadgeID&lt;/code&gt; is referenced by &lt;code&gt;labUserExtension&lt;/code&gt;, which is linked to &lt;code&gt;user&lt;/code&gt;. An attribute can only be deactivated (&lt;code&gt;isDefunct&lt;/code&gt;) when no active class uses it. So in practice, extensions like this one stay in the forest for good. Leave it in place; it's harmless and clearly named.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deactivation drill.&lt;/strong&gt; Practise on a standalone attribute that no class references:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drill step 1. Create the attribute first.&lt;/strong&gt; You can only deactivate an object that exists. Save as &lt;code&gt;C:\Lab\schema-testdefunct.ldf&lt;/code&gt;, using your base OID + &lt;code&gt;.1.2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: CN=lab-TestDefunct,DC=X
changetype: add
objectClass: attributeSchema
lDAPDisplayName: labTestDefunct
adminDisplayName: lab-TestDefunct
adminDescription: Lab attribute for the deactivation drill
attributeID: &amp;lt;BASE&amp;gt;.1.2
attributeSyntax: 2.5.5.12
oMSyntax: 64
isSingleValued: TRUE
searchFlags: 0

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ldifde&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab\schema-testdefunct.ldf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DC=X"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#schemaNamingContext"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Lab&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Confirm it exists before deactivating&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADRootDSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schemaNamingContext&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SearchBase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lDAPDisplayName -eq 'labTestDefunct'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;attributeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isDefunct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drill step 2. Deactivate it&lt;/strong&gt; with &lt;code&gt;C:\Lab\schema-defunct.ldf&lt;/code&gt;, imported on the Schema Master (&lt;code&gt;-s DC01&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: CN=lab-TestDefunct,DC=X
changetype: modify
replace: isDefunct
isDefunct: TRUE
-

dn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drill step 3.&lt;/strong&gt; Import it with the same &lt;code&gt;ldifde&lt;/code&gt; command. In the Schema snap-in, the attribute now shows as deactivated, but the object still exists. That is what "no deletions" means.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cleanup:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Set-ADUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;testuser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Clear&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;labEmployeeBadgeID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Remove-ADGroupMember&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Identity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schema Admins"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Members&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your admin account&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Confirm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign out and back in, then confirm that &lt;code&gt;whoami /groups&lt;/code&gt; no longer lists Schema Admins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tasks 2–5 exercise notes: schema extension on DC01, 28 Oct 2026
&lt;/h3&gt;

&lt;p&gt;The next day I ran Tasks 2 to 5. The schema change itself worked. Almost everything that went wrong was me: placeholders I typed literally, a PowerShell quirk, and doing a step in the wrong order. The run log below lists every attempt, including the failed ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;lab-EmployeeBadgeID&lt;/code&gt; and &lt;code&gt;lab-UserExtension&lt;/code&gt; were created, linked to &lt;code&gt;user&lt;/code&gt;, and tested on &lt;strong&gt;Bob.Tester&lt;/strong&gt; (&lt;code&gt;B-1001&lt;/code&gt;). The deactivation drill worked once &lt;code&gt;lab-TestDefunct&lt;/code&gt; was created first. Schema Admins membership was removed at the end. All work ran on DC01, which now holds the Schema Master role.&lt;/p&gt;

&lt;h4&gt;
  
  
  Role change before the exercise
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;FSMO role&lt;/th&gt;
&lt;th&gt;27 Oct (Task 1)&lt;/th&gt;
&lt;th&gt;28 Oct&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Schema Master&lt;/td&gt;
&lt;td&gt;DC02&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;DC01&lt;/strong&gt; (transferred)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain naming, PDC, RID, Infrastructure&lt;/td&gt;
&lt;td&gt;DC01&lt;/td&gt;
&lt;td&gt;DC01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All five roles are now on DC01, so every &lt;code&gt;ldifde -s&lt;/code&gt; in this guide targets DC01.&lt;/p&gt;

&lt;h4&gt;
  
  
  Objects created
&lt;/h4&gt;

&lt;p&gt;Base OID: &lt;code&gt;1.2.840.113556.1.8000.2554.37133.11732.61101.19326.42313.5642591.8298009&lt;/code&gt;, saved in &lt;code&gt;C:\Lab\BaseOID.txt&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;OID&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;lab-EmployeeBadgeID (&lt;code&gt;labEmployeeBadgeID&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Attribute, Unicode string, max 32&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Active, used by lab-UserExtension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lab-UserExtension (&lt;code&gt;labUserExtension&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Auxiliary class&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.2.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Linked to &lt;code&gt;user&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lab-TestDefunct (&lt;code&gt;labTestDefunct&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Attribute, no class&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;BASE&amp;gt;.1.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deactivated (drill)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Run log
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;OID generator script&lt;/td&gt;
&lt;td&gt;First run failed: typo &lt;code&gt;NewGui//d()&lt;/code&gt; gave a parser error. Rerun with &lt;code&gt;NewGuid()&lt;/code&gt; worked.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;BASE&amp;gt;.1.1&lt;/code&gt; typed at the prompt&lt;/td&gt;
&lt;td&gt;Error: &lt;code&gt;&amp;lt;&lt;/code&gt; is not a command. &lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt; is a placeholder in the guide, not something to run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$BaseOID.1.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returned nothing: PowerShell reads &lt;code&gt;.1&lt;/code&gt; as a property name. Use &lt;code&gt;"$BaseOID.1.1"&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;schema-lab.ldf&lt;/code&gt; written in Notepad, checked with &lt;code&gt;Select-String&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Both OIDs present, no &lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt; left ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ldifde -i -f schema-lab.ldf -s DC01 …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Attribute and class created ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ldifde -i -f schema-link.ldf -s DC01 …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;labUserExtension&lt;/code&gt; added to &lt;code&gt;user&lt;/code&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Set-ADUser testuser …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not found: no account called &lt;code&gt;testuser&lt;/code&gt; in the lab. Used &lt;code&gt;Bob.Tester&lt;/code&gt; (OU=Lab Users).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Set-ADUser Bob.Tester -Replace @{labEmployeeBadgeID = "B-1001"}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value written; &lt;code&gt;Get-ADUser&lt;/code&gt; and LDAP filter &lt;code&gt;(labEmployeeBadgeID=B-*)&lt;/code&gt; both returned Bob Tester ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ldifde -i -f schema-defunct.ldf …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0x208D NO_OBJECT&lt;/code&gt;, best match &lt;code&gt;CN=Schema,…&lt;/code&gt;: &lt;code&gt;lab-TestDefunct&lt;/code&gt; did not exist yet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Created it with &lt;code&gt;schema-testdefunct.ldf&lt;/code&gt;, then reran step 9&lt;/td&gt;
&lt;td&gt;Deactivation succeeded ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-ADObject … -Filter "lDAPDisplayName -like 'lab*'"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Listed the lab objects plus built-in &lt;code&gt;labeledURI&lt;/code&gt;. The class shows no &lt;code&gt;attributeID&lt;/code&gt; because classes use &lt;code&gt;governsID&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Set-ADUser Bob.Tester -Clear labEmployeeBadgeID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value cleared ✅ (an earlier &lt;code&gt;Set-ADUser testuser Bob.Tester …&lt;/code&gt; failed: no positional parameter)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Remove-ADGroupMember "Schema Admins" -Members adminstrator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removed ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The mistake worth remembering:&lt;/strong&gt; step 9. I tried to deactivate an attribute I hadn't created yet. &lt;code&gt;NO_OBJECT&lt;/code&gt; with a "best match" of &lt;code&gt;CN=Schema&lt;/code&gt; is AD telling you the parent container exists but the object you named doesn't. Once I read it that way, the fix was obvious.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Lessons learned
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;An .ldf file is plain text. &lt;code&gt;ldifde&lt;/code&gt; cannot read PowerShell variables, so OIDs must be written out in full.&lt;/li&gt;
&lt;li&gt;Inside PowerShell, build OIDs as strings: &lt;code&gt;"$BaseOID.1.1"&lt;/code&gt;, not &lt;code&gt;$BaseOID.1.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Names in a guide (&lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt;, &lt;code&gt;testuser&lt;/code&gt;) are placeholders. Check real names first: &lt;code&gt;Get-ADUser -Filter "Name -like '*test*'"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NO_OBJECT&lt;/code&gt; with a "best match" means the parent exists but the object does not. Create before you modify or deactivate.&lt;/li&gt;
&lt;li&gt;Attributes are identified by &lt;code&gt;attributeID&lt;/code&gt;; classes by &lt;code&gt;governsID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The prefix &lt;code&gt;lab&lt;/code&gt; also matched the built-in &lt;code&gt;labeledURI&lt;/code&gt;. In production, use a unique company prefix (for example &lt;code&gt;contoso-&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Transferring the Schema Master changes which DC every schema import must target. Run &lt;code&gt;netdom query fsmo&lt;/code&gt; before each change.&lt;/li&gt;
&lt;li&gt;In Windows PowerShell 5.1, the transcript did &lt;strong&gt;not&lt;/strong&gt; record the output of &lt;code&gt;ldifde&lt;/code&gt;, &lt;code&gt;repadmin&lt;/code&gt; and &lt;code&gt;netdom&lt;/code&gt;. Pipe them through &lt;code&gt;| Out-Host&lt;/code&gt; to capture it, and check &lt;code&gt;C:\Lab\ldif.log&lt;/code&gt; / &lt;code&gt;ldif.err&lt;/code&gt;, which &lt;code&gt;-j C:\Lab&lt;/code&gt; writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Still to verify (output not captured in the transcript)
&lt;/h4&gt;

&lt;p&gt;That last lesson has a cost: some results I saw on screen never made it into my log. Until I re-run these checks and keep the output, I'm treating them as not verified.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;☐ &lt;code&gt;labTestDefunct&lt;/code&gt; shows &lt;code&gt;isDefunct = True&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;☐ Lab attribute and class visible on DC02 (Task 5 replication check)&lt;/li&gt;
&lt;li&gt;☐ &lt;code&gt;netdom query fsmo&lt;/code&gt; shows DC01 for all five roles&lt;/li&gt;
&lt;li&gt;☐ &lt;code&gt;repadmin /replsummary&lt;/code&gt; shows 0 failures after the schema changes&lt;/li&gt;
&lt;li&gt;☐ After signing out and in, &lt;code&gt;whoami /groups&lt;/code&gt; no longer lists Schema Admins
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-ADRootDSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schemaNamingContext&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Get-ADObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DC02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SearchBase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$schemaNC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lDAPDisplayName -like 'lab*'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;attributeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;governsID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isDefunct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;attributeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;governsID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;isDefunct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;netdom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fsmo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Host&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;repadmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/replsummary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Host&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;whoami&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/groups&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting, checklist and blog notes
&lt;/h2&gt;

&lt;p&gt;If you run this lab yourself, these are the errors you're most likely to hit, and where each one comes from.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Insufficient access rights&lt;/code&gt; on import&lt;/td&gt;
&lt;td&gt;Old logon token without Schema Admins&lt;/td&gt;
&lt;td&gt;Sign out and back in, check &lt;code&gt;whoami /groups&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Unwilling to perform&lt;/code&gt; / referral&lt;/td&gt;
&lt;td&gt;Import not aimed at the Schema Master&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;-s &amp;lt;Schema Master&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Entry already exists&lt;/code&gt; / OID conflict&lt;/td&gt;
&lt;td&gt;Name or OID reused&lt;/td&gt;
&lt;td&gt;New &lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt; value, check the snap-in first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Set-ADUser&lt;/code&gt; says attribute unknown&lt;/td&gt;
&lt;td&gt;Schema cache not refreshed&lt;/td&gt;
&lt;td&gt;Update Schema Now, then a new PowerShell window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attribute missing on DC02&lt;/td&gt;
&lt;td&gt;Replication delay or failure&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;repadmin /syncall /AdeP&lt;/code&gt;, &lt;code&gt;repadmin /showrepl&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema snap-in not in MMC list&lt;/td&gt;
&lt;td&gt;DLL not registered&lt;/td&gt;
&lt;td&gt;&lt;code&gt;regsvr32 schmmgmt.dll&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;☐ Task 1 baseline recorded (Schema Master, objectVersion, replsummary clean)&lt;/li&gt;
&lt;li&gt;☐ Snapshot and checkpoint taken&lt;/li&gt;
&lt;li&gt;☐ Schema Admins added and token refreshed&lt;/li&gt;
&lt;li&gt;☐ Attribute and auxiliary class imported&lt;/li&gt;
&lt;li&gt;☐ Class linked to user, value written and read back&lt;/li&gt;
&lt;li&gt;☐ Value confirmed on DC02&lt;/li&gt;
&lt;li&gt;☐ Deactivation drill done&lt;/li&gt;
&lt;li&gt;☐ Schema Admins membership removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-world takeaway: Exchange (&lt;code&gt;/PrepareSchema&lt;/code&gt;), Windows LAPS (&lt;code&gt;Update-LapsADSchema&lt;/code&gt;) and ConfigMgr (&lt;code&gt;extadsch.exe&lt;/code&gt;) all do exactly what you did here, just with vendor-registered OIDs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took away from this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The baseline is the most important step.&lt;/strong&gt; It took longer than the schema change itself, and it found the one problem that would have silently broken everything after it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know where the Schema Master is, every time.&lt;/strong&gt; Mine moved twice in a week, and every &lt;code&gt;ldifde -s&lt;/code&gt; depended on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Passed" can be out of date.&lt;/strong&gt; A replication error can stay in the report long after its cause is gone. Force a fresh attempt before you believe either the error or the fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read placeholders as placeholders.&lt;/strong&gt; Half my run-log errors came from typing &lt;code&gt;&amp;lt;BASE&amp;gt;&lt;/code&gt; or &lt;code&gt;testuser&lt;/code&gt; literally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permanent means permanent.&lt;/strong&gt; The badge attribute is in my forest for good. That's fine in a lab with clear &lt;code&gt;lab-&lt;/code&gt; names, and it's exactly why production teams test in a separate forest first.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This came from my own Active Directory lab, so your results will differ. If you've extended the schema in production, or hit 8524 in a different way, I'd like to hear about it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>activedirectory</category>
      <category>powershell</category>
      <category>sysadmin</category>
      <category>windowsserver</category>
    </item>
    <item>
      <title>Conquering Windows Server 2022: How to Manually Sideload Winget (Without the Microsoft Store)</title>
      <dc:creator>Suat Can Geyik</dc:creator>
      <pubDate>Sun, 10 May 2026 20:51:10 +0000</pubDate>
      <link>https://dev.to/scg/conquering-windows-server-2022-how-to-manually-sideload-winget-without-the-microsoft-store-2pmg</link>
      <guid>https://dev.to/scg/conquering-windows-server-2022-how-to-manually-sideload-winget-without-the-microsoft-store-2pmg</guid>
      <description>&lt;p&gt;Ever try to run a simple, modern command on a simplified Server OS?&lt;/p&gt;

&lt;p&gt;Recently, I deployed a Windows Server 2022 machine in my Azure tenant and needed to use Winget (the Windows Package Manager) to streamline my environment. It sounds like a standard five-minute task.&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;Because Server 2022 lacks the Microsoft Store by default, it also lacks the background infrastructure to manage modern app dependencies. What started as a simple command turned into a deep dive into missing UWP frameworks, architecture mismatches, and XML digital licenses.&lt;/p&gt;

&lt;p&gt;Instead of doing things the old-fashioned way, I reverse-engineered the deployment process. Here is the step-by-step documentation for manually injecting dependencies and getting Winget running natively on a very basic Server OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Environment Preparation and Execution Bypass
&lt;/h2&gt;

&lt;p&gt;Before running package installation commands, we need to prepare the PowerShell environment to allow secure web communication and script execution. Open PowerShell as an Administrator and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Force PowerShell to use TLS 1.2 for secure web connections&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Net.ServicePointManager&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SecurityProtocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Net.SecurityProtocolType&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Tls12&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Temporarily bypass script execution restrictions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-ExecutionPolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Bypass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Create and navigate to a working directory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-Location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Logic&lt;/strong&gt;: Modern endpoints (like GitHub) strictly require TLS 1.2. Forcing this ensures the connection isn't rejected. Additionally, setting the execution policy to Bypass temporarily lifts Server 2022's strict script restrictions just for this active window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Acquiring the Installation Assets
&lt;/h2&gt;

&lt;p&gt;PowerShell's &lt;code&gt;Invoke-WebRequest&lt;/code&gt; can occasionally fail on Azure VMs due to redirects. Downloading the assets manually via a web browser (like Edge) is the most reliable approach.&lt;/p&gt;

&lt;p&gt;Navigate to the official Winget releases page:&lt;br&gt;
&lt;a href="https://github.com/microsoft/winget-cli/releases" rel="noopener noreferrer"&gt;Github winget releases&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Locate the release with the green &lt;strong&gt;Latest&lt;/strong&gt; tag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll to the Assets section and download these three items to your &lt;code&gt;C:\winget-init&lt;/code&gt; folder:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DesktopAppInstaller_Dependencies.zip&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;XML License file&lt;/strong&gt; (e.g., &lt;code&gt;e53e159d00e04f729cc2180cffd1c02e_License1.xml&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Extract the contents of &lt;code&gt;DesktopAppInstaller_Dependencies.zip&lt;/code&gt; into your working folder.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Step 3: Framework &amp;amp; Dependency Injection
&lt;/h2&gt;

&lt;p&gt;The Server OS requires exact architectural dependencies (64-bit/x64) to be installed before the main application. Locate the extracted &lt;code&gt;_x64&lt;/code&gt;framework files (specifically VCLibs and UI.Xaml) and install them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Install the 64-bit Visual C++ libraries&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Add-AppxPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init\Microsoft.VCLibs.x64.14.00.Desktop.appx"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Install the 64-bit UI Xaml framework&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Add-AppxPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init\Microsoft.UI.Xaml.2.8.x64.appx"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Logic:&lt;/strong&gt; Winget is a 64-bit application. If you attempt to install the x86 (32-bit) dependencies, the installation will fail with a 0x80073CF3 conflict error. We are manually fulfilling the prerequisites that the Microsoft Store normally handles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Engine Installation
&lt;/h2&gt;

&lt;p&gt;With the prerequisites in place, install the main application bundle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Add-AppxPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: System-Wide Licensing (The Final Fix)
&lt;/h2&gt;

&lt;p&gt;If you run &lt;code&gt;winget&lt;/code&gt; now, it will return a "No applicable app licenses found" error. Because Server 2022 lacks the Store to verify digital entitlements, you must manually inject the XML license into the OS image using DISM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Add-AppxProvisionedPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Online&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-PackagePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LicensePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\winget-init\e53e159d00e04f729cc2180cffd1c02e_License1.xml"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Logic:&lt;/strong&gt; &lt;code&gt;Add-AppxProvisionedPackage&lt;/code&gt; provisions the app so that it is officially licensed and available for any user that logs into this server, bypassing the Store verification entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Verification and Cleanup
&lt;/h2&gt;

&lt;p&gt;Close your current PowerShell window to refresh the environment variables, open a new session, and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once verified, you have successfully built a modern Package Manager environment on a legacy architecture&lt;/p&gt;

</description>
      <category>windows</category>
      <category>powershell</category>
      <category>azure</category>
      <category>sysadmin</category>
    </item>
  </channel>
</rss>
