As reported here and here, a Server 2025 domain controller does not properly detect that it is on the domain. The Server 2022 workaround, with registry entries like AlwaysExpectDomainController that I blogged here, no longer works. The workaround is to restart the Public network adapter(s) after each server boot.
I used Gemini to write a PowerShell script that would restart Public network adapters. It took quite a bit of debugging, and I tweaked some of the logging. Here’s the script. As always, use at your own risk!
<# .Synopsis Find network adapters with NetworkCategory = Public and restart them. Run this a minute after each Server 2025 Domain Controller restart to get the DC back on the domain. This writes to the Application event log with Source "IT Script" and Event IDs 1100 - 1104. Copyright (c) 2025 by MCB Systems. All rights reserved. Free for personal or commercial use. May not be sold. No warranties. Use at your own risk. .Notes Name: MCB.RestartPublicNetAdapters.ps1 Author: Mark Berry, MCB Systems Created: 03/19/2025 Last Edit: 03/19/2025 Changes: #> ################################################################################ # Functions ################################################################################ # Function to write messages to both console and event log. function Write-Log { param ( [string]$Message, [string]$Type = "Information", # Information, Warning, Error [int]$EventId = 0 # Default Event ID ) # Prepend the name (not the full path) of the running script $Message = (Split-Path $PSCommandPath -Leaf) + ": " + $Message switch ($Type) { "Information" { Write-Host $Message Write-EventLog -LogName $EventLogName -Source $EventLogSource -EntryType Information -Message $Message -EventId $EventId } "Warning" { Write-Warning $Message Write-EventLog -LogName $EventLogName -Source $EventLogSource -EntryType Warning -Message $Message -EventId $EventId } "Error" { Write-Error $Message Write-EventLog -LogName $EventLogName -Source $EventLogSource -EntryType Error -Message $Message -EventId $EventId } } } ################################################################################ # Setup ################################################################################ $EventLogName = "Application" $EventLogSource = "IT Script" $WaitSeconds = 30 # Check if the event source exists, create it if not if (-not ([System.Diagnostics.EventLog]::SourceExists($EventLogSource))) { New-EventLog -LogName $EventLogName -Source $EventLogSource } ################################################################################# # Check for Public adapters and restart ################################################################################ # Get all network adapters with NetworkCategory "Public" # The (@(...)) operator ensures that the result of the pipeline is always treated as an array, even if it contains only one element. $PublicAdapters = @(Get-NetConnectionProfile | ` Where-Object {$_.NetworkCategory -eq "Public"} | ` ForEach-Object { Get-NetAdapter -InterfaceAlias $_.InterfaceAlias }) # Check if any public adapters were found if ($PublicAdapters.Count -gt 0) { Write-Log "Found $($PublicAdapters.Count) Public network adapter(s). Will attempt restart to re-detect domain." -EventId 1100 # Loop through each public adapter and restart it foreach ($Adapter in $PublicAdapters) { try { $NetworkCategory = (Get-NetConnectionProfile -InterfaceAlias $Adapter.Name).NetworkCategory # shoudl be Public, but re-confirm Write-Log "Restarting adapter: $($Adapter.Name), which is currently $NetworkCategory." -EventId 1101 Restart-NetAdapter -Name $Adapter.Name -Confirm:$false Write-Log "Waiting $WaitSeconds seconds for Windows to identify the domain." Start-Sleep -Seconds $WaitSeconds $NetProfile = Get-NetConnectionProfile -InterfaceAlias $Adapter.Name $NetProfileName = $NetProfile.Name $NetworkCategory = $NetProfile.NetworkCategory if ($NetProfileName -eq "Identifying...") { Write-Log "Adapter $($Adapter.Name) restarted successfully. After waiting $WaitSeconds seconds, its Name still shows as $NetProfileName, so the NetworkCategory $NetworkCategory is not final." -EventId 1102 } else { Write-Log "Adapter $($Adapter.Name) restarted successfully. Its Name is now $NetProfileName and its NetworkCategory is $NetworkCategory." -EventId 1103 } } catch { Write-Log "Failed to restart adapter $($Adapter.Name): $($_.Exception.Message)" -Type Error -EventId 1104 } } } else { Write-Log "No Public network adapters found, so no adapters restarted." -EventId 1105 }
I’ve deployed that as follows:
1. Put the script on the server.
2. Create a RestartPublicNetAdapters.cmd file to run the script, for example:
cd /d C:\Scripts\PowerShell
powershell.exe -NoLogo -NoProfile -NonInteractive ".\MCB.RestartPublicNetAdapters.ps1" ; exit $LASTEXITCODE
3. In Task Scheduler, create a task to call RestartPublicNetAdapters.cmd one minute after each system start. Run the task as SYSTEM with highest privileges.
Nice one thank you Mark.