Add Windows MDM migration troubleshooting scripts and guide (#39548)
Closes #38916 Related: #34993, #33985, fleetdm/confidential#13228 ## Changes **Article update** (`articles/windows-mdm-setup.md`) - Adds "Migrating from another MDM solution" subsection under **Manual enrollment** with overview of common migration issues and links to remediation scripts **New scripts** (`docs/solutions/windows/scripts/`) - `reset-mdm-enrollment-flag.ps1` — Resets MmpcEnrollmentFlag blocking MDM status after migration - `remove-stale-mdm-enrollment-records.ps1` — Clears orphaned enrollment GUIDs, AAD discovery cache, and MS DM Server cache - `fix-workplace-join-configuration.ps1` — Re-enables Automatic-Device-Join task and configures Workplace Join policies - `remove-unreachable-wsus-configuration.ps1` — Removes unreachable WSUS server config that breaks Windows Update ## Context Customers migrating Windows hosts from Intune to Fleet have been hitting recurring enrollment issues, MDM status stuck on "Off," enrollment errors (`0x80190190`, `0x8018000a`), and Windows Update breakage from leftover RMM agents. These scripts consolidate the workarounds from multiple customer engagements into self-serve remediation that can be deployed via **Controls > Scripts**. --------- Co-authored-by: Marko Lisica <83164494+marko-lisica@users.noreply.github.com>
This commit is contained in:
co-authored by
Marko Lisica
parent
b7d9683fc5
commit
f2f1f66d11
@@ -47,6 +47,24 @@ With Windows MDM turned on, enroll a Windows host to Fleet by installing [Fleet'
|
||||
|
||||
> Windows [tamper protection](https://learn.microsoft.com/en-us/defender-endpoint/prevent-changes-to-security-settings-with-tamper-protection) is disabled on a host when MDM is turned on.
|
||||
|
||||
### Migrating from another MDM solution
|
||||
|
||||
When migrating Windows hosts from another MDM, devices may fail to report MDM as "On." You might see enrollment errors (e.g., 400 or 0x8018000a) in [fleetd logs](https://fleetdm.com/guides/enroll-hosts#debugging).
|
||||
|
||||
These issues are caused by residual enrollment data, registry conflicts, or third-party management agents from the previous MDM solution. [Run the scripts](https://fleetdm.com/guides/scripts#manually-run-scripts) below on the affected hosts, then **reboot the device** and select **Refetch** on the host details.
|
||||
|
||||
|
||||
- [reset-mdm-enrollment-flag.ps1](https://github.com/fleetdm/fleet/blob/main/docs/solutions/windows/scripts/reset-mdm-enrollment-flag.ps1): Resets the `MmpcEnrollmentFlag` registry value to fix incorrect MDM status reporting after migration.
|
||||
|
||||
|
||||
- [remove-stale-mdm-enrollment-records.ps1](https://github.com/fleetdm/fleet/blob/main/docs/solutions/windows/scripts/remove-stale-mdm-enrollment-records.ps1): Removes failed or orphaned MDM enrollment records, AAD discovery cache, and MS DM Server cache left behind by the previous MDM solution.
|
||||
|
||||
- [fix-workplace-join-configuration.ps1](https://github.com/fleetdm/fleet/blob/main/docs/solutions/windows/scripts/fix-workplace-join-configuration.ps1): Re-enables the Automatic-Device-Join scheduled task and fixes Workplace Join policies that may be misconfigured after migration.
|
||||
|
||||
- [remove-unreachable-wsus-configuration.ps1](https://github.com/fleetdm/fleet/blob/main/docs/solutions/windows/scripts/remove-unreachable-wsus-configuration.ps1): Removes stale WSUS server configurations that can break Windows Update after migration. Only removes the configuration if the WSUS server is unreachable.
|
||||
|
||||
**Conflicting RMM or management agents:** Third-party RMM agents (such as N-able/SolarWinds, ConnectWise, or Kaseya) installed alongside the previous MDM solution can interfere with Fleet's MDM enrollment and may cause Windows Update to stop functioning. Check for and remove any RMM agents that are no longer needed before or after migrating to Fleet.
|
||||
|
||||
## Automatic enrollment
|
||||
|
||||
> Available in Fleet Premium
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Please don't delete. This script is referenced in the guide here: https://fleetdm.com/guides/windows-mdm-setup#migrating-from-another-mdm-solution
|
||||
# Re-enables the Automatic-Device-Join scheduled task and configures Workplace Join policies
|
||||
# that may be misconfigured after migrating from another MDM solution.
|
||||
# Reboot the device after running this script.
|
||||
|
||||
# 1. Re-enable Automatic-Device-Join scheduled task
|
||||
$TaskPath = "\Microsoft\Windows\Workplace Join\"
|
||||
$TaskName = "Automatic-Device-Join"
|
||||
try {
|
||||
$task = Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction Stop
|
||||
Enable-ScheduledTask -InputObject $task
|
||||
Write-Host "Re-enabled Automatic-Device-Join task"
|
||||
} catch {
|
||||
Write-Host "Automatic-Device-Join task not found - skipping"
|
||||
}
|
||||
|
||||
# 2. Configure Workplace Join policy
|
||||
$WJPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WorkplaceJoin"
|
||||
if (-not (Test-Path $WJPath)) { New-Item -Path $WJPath -Force | Out-Null }
|
||||
Set-ItemProperty -Path $WJPath -Name "autoWorkplaceJoin" -Value 1 -Type DWord
|
||||
Set-ItemProperty -Path $WJPath -Name "BlockAADWorkplaceJoin" -Value 0 -Type DWord
|
||||
Write-Host "Configured Workplace Join policy"
|
||||
@@ -0,0 +1,41 @@
|
||||
# Please don't delete. This script is referenced in the guide here: https://fleetdm.com/guides/windows-mdm-setup#migrating-from-another-mdm-solution
|
||||
# Removes stale MDM enrollment registry entries, AAD discovery cache, and MS DM Server cache
|
||||
# that can block Fleet MDM enrollment after migrating from another MDM solution.
|
||||
# Reboot the device after running this script.
|
||||
|
||||
# 1. Clear the AAD discovery cache
|
||||
$AADPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CDJ\AAD"
|
||||
if (Test-Path $AADPath) {
|
||||
Remove-Item -Path $AADPath -Recurse -Force
|
||||
Write-Host "Cleared AAD discovery cache"
|
||||
} else {
|
||||
Write-Host "AAD discovery cache not found - skipping"
|
||||
}
|
||||
|
||||
# 2. Remove stale GUID-based enrollment entries (failed, removed, or error states)
|
||||
$EnrollmentPath = "HKLM:\SOFTWARE\Microsoft\Enrollments"
|
||||
$cleaned = 0
|
||||
Get-ChildItem -Path $EnrollmentPath -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
if ($_.PSChildName -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') {
|
||||
$state = (Get-ItemProperty -Path $_.PSPath -Name "EnrollmentState" -ErrorAction SilentlyContinue).EnrollmentState
|
||||
# EnrollmentState: 0=Not enrolled, 1=Enrolled, 2=Failed, 3=Removed, 4=Failed (old may still work)
|
||||
if ($state -in @(2, 3, 4)) {
|
||||
Remove-Item -Path $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "Removed stale enrollment: $($_.PSChildName) (state: $state)"
|
||||
$cleaned++
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Host "Cleaned $cleaned stale enrollment entries"
|
||||
|
||||
# 3. Clear MS DM Server cache
|
||||
if (Test-Path "HKLM:\SOFTWARE\Microsoft\MSDM\Server") {
|
||||
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\MSDM\Server\*" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "Cleared MS DM Server cache"
|
||||
} else {
|
||||
Write-Host "MS DM Server cache not found - skipping"
|
||||
}
|
||||
|
||||
# 4. Restart Device Registration Service
|
||||
Restart-Service -Name "DsSvc" -ErrorAction SilentlyContinue
|
||||
Write-Host "Restarted Device Registration Service"
|
||||
@@ -0,0 +1,40 @@
|
||||
# Please don't delete. This script is referenced in the guide here: https://fleetdm.com/guides/windows-mdm-setup#migrating-from-another-mdm-solution
|
||||
# Detects and removes unreachable WSUS server configurations that can break Windows Update
|
||||
# after migrating from another MDM solution. Only removes WSUS config if the server cannot
|
||||
# be reached at all (HTTP error responses like 403 are treated as reachable).
|
||||
# Reboot the device after running this script.
|
||||
|
||||
$WUPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
|
||||
if (-not (Test-Path $WUPath)) {
|
||||
Write-Host "Windows Update policy path not found - no action needed"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$wuServer = (Get-ItemProperty -Path $WUPath -Name "WUServer" -ErrorAction SilentlyContinue).WUServer
|
||||
if (-not $wuServer) {
|
||||
Write-Host "No WSUS server configured - no action needed"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$reachable = $false
|
||||
try {
|
||||
$null = Invoke-WebRequest -Uri $wuServer -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop
|
||||
$reachable = $true
|
||||
} catch [System.Net.WebException] {
|
||||
if ($_.Exception.Response) {
|
||||
# Server responded with an HTTP error (e.g., 403) - it is still reachable
|
||||
$reachable = $true
|
||||
}
|
||||
} catch {
|
||||
# Connection failed entirely
|
||||
}
|
||||
|
||||
if ($reachable) {
|
||||
Write-Host "WSUS server $wuServer is reachable - no action taken"
|
||||
} else {
|
||||
Write-Host "WSUS server $wuServer is unreachable - removing configuration"
|
||||
Remove-ItemProperty -Path $WUPath -Name "WUServer" -ErrorAction SilentlyContinue
|
||||
Remove-ItemProperty -Path $WUPath -Name "WUStatusServer" -ErrorAction SilentlyContinue
|
||||
Restart-Service wuauserv -Force
|
||||
Write-Host "Windows Update service restarted"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# Please don't delete. This script is referenced in the guide here: https://fleetdm.com/guides/windows-mdm-setup#migrating-from-another-mdm-solution
|
||||
# Resets the MmpcEnrollmentFlag registry value that can prevent Fleet from reporting
|
||||
# MDM status correctly after migrating from another MDM solution (e.g., Intune).
|
||||
# Reboot the device after running this script.
|
||||
|
||||
$enrollmentsPath = "HKLM:\SOFTWARE\Microsoft\Enrollments"
|
||||
$enrollmentFlag = (Get-ItemProperty -Path $enrollmentsPath -Name "MmpcEnrollmentFlag" -ErrorAction SilentlyContinue).MmpcEnrollmentFlag
|
||||
if ($null -ne $enrollmentFlag -and 0 -ne $enrollmentFlag) {
|
||||
Write-Host "Enrollment flag current value $enrollmentFlag - setting to 0"
|
||||
Set-ItemProperty -Path $enrollmentsPath -Name "MmpcEnrollmentFlag" -Value 0 -Type DWord
|
||||
} else {
|
||||
Write-Host "Enrollment flag already 0 or does not exist"
|
||||
}
|
||||
Reference in New Issue
Block a user