[{"data":1,"prerenderedAt":1999},["ShallowReactive",2],{"post:\u002F2026\u002F04\u002F01\u002Fintune-migrating-from-group-policy-to-cloud-native-endpoint-management\u002F":3},{"post":4,"newer":1950,"older":1958,"related":1968,"series":1997},{"id":5,"title":6,"body":7,"canonical":1929,"categories":1930,"date":1933,"description":1934,"extension":1935,"featured":1936,"hero":1937,"image":1937,"meta":1938,"navigation":190,"path":1939,"readingTime":90,"seo":1940,"series":1937,"seriesOrder":1937,"sites":1941,"source":1937,"stem":1942,"tags":1943,"updated":1937,"url":1948,"__hash__":1949},"blog\u002Fblog\u002F2026\u002F04\u002F01\u002Fintune-migrating-from-group-policy-to-cloud-native-endpoint-management.md","Intune: Migrating From Group Policy to Cloud-Native Management",{"type":8,"value":9,"toc":1920},"minimark",[10,14,17,22,25,33,999,1002,1010,1025,1029,1045,1087,1093,1097,1110,1114,1117,1131,1139,1143,1150,1159,1209,1212,1222,1844,1851,1855,1858,1861,1865,1916],[11,12,13],"p",{},"Group Policy has been the backbone of Windows management for two decades, and it still works, which is exactly why moving off it is uncomfortable. Nobody migrates away from something broken by comparison; they migrate away from something that quietly does its job while the rest of the environment moves toward devices that never touch the corporate network at all. That was the real driver in the environments I've helped move to Intune: not that GPO failed, but that it only reaches machines that can see a domain controller, and an increasing share of a modern fleet never does.",[11,15,16],{},"This is the sequence I use now, with the scripts that go with each step.",[18,19,21],"h2",{"id":20},"inventory-before-you-touch-anything","Inventory before you touch anything",[11,23,24],{},"The first mistake is starting in Intune and working backward. The right first step is exporting every GPO that's actually linked, not the ones sitting unlinked in the GPO store from a project three reorganizations ago, and cataloging what each setting does, who it affects, and whether it's still relevant. Every estate I've done this in carried dead weight: settings for a VPN client that was decommissioned, drive mappings to a file server that moved, a login script nobody remembers writing. Migrating dead policy is wasted work. Cutting it first shrinks the real migration to something manageable.",[11,26,27,28,32],{},"The script below does the mechanical half. It needs the ",[29,30,31],"code",{},"GroupPolicy"," module (RSAT Group Policy Management Tools) and read access to the domain's GPOs. For every GPO it writes the XML report that Intune's Group Policy analytics imports, then builds a CSV with link status, which halves are disabled, last modification time, and whether the XML is over the 4 MB import limit.",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-powershell shiki shiki-themes github-dark","\u003C#\n.SYNOPSIS\n    Exports every GPO in the domain to XML and builds a link inventory CSV.\n.DESCRIPTION\n    Uses Get-GPO -All and Get-GPOReport -ReportType Xml to write one XML report\n    per GPO (the format Intune Group Policy analytics imports), then reads each\n    report's LinksTo entries to record where the GPO is linked and whether the\n    link is enabled. Flags unlinked GPOs, GPOs with all settings disabled, and\n    reports over the 4 MB Group Policy analytics import limit.\n.PARAMETER OutputFolder\n    Folder for the XML reports and gpo-inventory.csv.\n.PARAMETER Domain\n    FQDN of the domain to read. Defaults to the current user's domain.\n.EXAMPLE\n    .\\Export-GpoInventory.ps1 -OutputFolder C:\\GpoExport\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2026-04-01)\n    Requires: GroupPolicy module (RSAT), read access to GPOs.\n#>\n\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory = $true)]\n    [string]$OutputFolder,\n\n    [Parameter()]\n    [string]$Domain = $env:USERDNSDOMAIN\n)\n\nImport-Module GroupPolicy\nNew-Item -Path $OutputFolder -ItemType Directory -Force | Out-Null\n\n$maxBytes = 4MB\n$inventory = foreach ($gpo in Get-GPO -All -Domain $Domain) {\n    $safeName = $gpo.DisplayName -replace '[\\\\\u002F:*?\"\u003C>|]', '_'\n    # Display names aren't guaranteed unique, so the GUID keeps each file distinct.\n    $xmlPath = Join-Path -Path $OutputFolder -ChildPath \"$safeName-$($gpo.Id).xml\"\n\n    Get-GPOReport -Guid $gpo.Id -ReportType Xml -Domain $Domain -Path $xmlPath\n    [xml]$report = Get-Content -Path $xmlPath -Raw\n\n    # Each LinksTo element is one link (SOMPath is the OU or domain path).\n    $links = @($report.GPO.LinksTo)\n    $enabledLinks = @($links | Where-Object { $_.Enabled -eq 'true' })\n    $size = (Get-Item -Path $xmlPath).Length\n\n    $candidate = 'Migrate or retire'\n    if ($enabledLinks.Count -eq 0) {\n        $candidate = 'Unlinked: review for deletion'\n    } elseif ($gpo.GpoStatus -eq 'AllSettingsDisabled') {\n        $candidate = 'All settings disabled'\n    }\n\n    [PSCustomObject]@{\n        Name             = $gpo.DisplayName\n        Id               = $gpo.Id\n        GpoStatus        = $gpo.GpoStatus\n        ModificationTime = $gpo.ModificationTime\n        LinkCount        = $links.Count\n        EnabledLinks     = $enabledLinks.Count\n        LinkedTo         = ($enabledLinks | ForEach-Object { $_.SOMPath }) -join '; '\n        ReportKB         = [math]::Round($size \u002F 1KB, 1)\n        OverImportLimit  = $size -gt $maxBytes\n        Candidate        = $candidate\n    }\n}\n\n$csvPath = Join-Path -Path $OutputFolder -ChildPath 'gpo-inventory.csv'\n$inventory | Sort-Object -Property EnabledLinks, Name | Export-Csv -Path $csvPath -NoTypeInformation -Encoding utf8\n$inventory | Group-Object -Property Candidate | Select-Object -Property Name, Count | Format-Table -AutoSize\nWrite-Host \"Wrote $(@($inventory).Count) reports and $csvPath\"\n","powershell","",[29,41,42,51,62,68,76,82,88,94,100,106,117,123,133,139,147,153,161,167,173,179,185,192,205,214,239,253,258,267,289,295,300,309,338,343,357,387,411,417,459,464,490,516,521,527,541,577,596,601,612,629,640,659,669,675,680,697,708,719,730,741,752,763,792,822,839,850,855,861,866,887,927,967],{"__ignoreMap":39},[43,44,47],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sAwPA","\u003C#\n",[43,52,54,58],{"class":45,"line":53},2,[43,55,57],{"class":56},"sDLfK",".",[43,59,61],{"class":60},"snl16","SYNOPSIS\n",[43,63,65],{"class":45,"line":64},3,[43,66,67],{"class":49},"    Exports every GPO in the domain to XML and builds a link inventory CSV.\n",[43,69,71,73],{"class":45,"line":70},4,[43,72,57],{"class":56},[43,74,75],{"class":60},"DESCRIPTION\n",[43,77,79],{"class":45,"line":78},5,[43,80,81],{"class":49},"    Uses Get-GPO -All and Get-GPOReport -ReportType Xml to write one XML report\n",[43,83,85],{"class":45,"line":84},6,[43,86,87],{"class":49},"    per GPO (the format Intune Group Policy analytics imports), then reads each\n",[43,89,91],{"class":45,"line":90},7,[43,92,93],{"class":49},"    report's LinksTo entries to record where the GPO is linked and whether the\n",[43,95,97],{"class":45,"line":96},8,[43,98,99],{"class":49},"    link is enabled. Flags unlinked GPOs, GPOs with all settings disabled, and\n",[43,101,103],{"class":45,"line":102},9,[43,104,105],{"class":49},"    reports over the 4 MB Group Policy analytics import limit.\n",[43,107,109,111,114],{"class":45,"line":108},10,[43,110,57],{"class":56},[43,112,113],{"class":60},"PARAMETER",[43,115,116],{"class":60}," OutputFolder\n",[43,118,120],{"class":45,"line":119},11,[43,121,122],{"class":49},"    Folder for the XML reports and gpo-inventory.csv.\n",[43,124,126,128,130],{"class":45,"line":125},12,[43,127,57],{"class":56},[43,129,113],{"class":60},[43,131,132],{"class":60}," Domain\n",[43,134,136],{"class":45,"line":135},13,[43,137,138],{"class":49},"    FQDN of the domain to read. Defaults to the current user's domain.\n",[43,140,142,144],{"class":45,"line":141},14,[43,143,57],{"class":56},[43,145,146],{"class":60},"EXAMPLE\n",[43,148,150],{"class":45,"line":149},15,[43,151,152],{"class":49},"    .\\Export-GpoInventory.ps1 -OutputFolder C:\\GpoExport\n",[43,154,156,158],{"class":45,"line":155},16,[43,157,57],{"class":56},[43,159,160],{"class":60},"NOTES\n",[43,162,164],{"class":45,"line":163},17,[43,165,166],{"class":49},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[43,168,170],{"class":45,"line":169},18,[43,171,172],{"class":49},"    Version : 1.0 (2026-04-01)\n",[43,174,176],{"class":45,"line":175},19,[43,177,178],{"class":49},"    Requires: GroupPolicy module (RSAT), read access to GPOs.\n",[43,180,182],{"class":45,"line":181},20,[43,183,184],{"class":49},"#>\n",[43,186,188],{"class":45,"line":187},21,[43,189,191],{"emptyLinePlaceholder":190},true,"\n",[43,193,195,199,202],{"class":45,"line":194},22,[43,196,198],{"class":197},"s95oV","[",[43,200,201],{"class":56},"CmdletBinding",[43,203,204],{"class":197},"()]\n",[43,206,208,211],{"class":45,"line":207},23,[43,209,210],{"class":60},"param",[43,212,213],{"class":197}," (\n",[43,215,217,220,223,226,230,233,236],{"class":45,"line":216},24,[43,218,219],{"class":197},"    [",[43,221,222],{"class":56},"Parameter",[43,224,225],{"class":197},"(",[43,227,229],{"class":228},"s9osk","Mandatory",[43,231,232],{"class":60}," =",[43,234,235],{"class":56}," $true",[43,237,238],{"class":197},")]\n",[43,240,242,244,247,250],{"class":45,"line":241},25,[43,243,219],{"class":197},[43,245,246],{"class":60},"string",[43,248,249],{"class":197},"]$OutputFolder",[43,251,252],{"class":60},",\n",[43,254,256],{"class":45,"line":255},26,[43,257,191],{"emptyLinePlaceholder":190},[43,259,261,263,265],{"class":45,"line":260},27,[43,262,219],{"class":197},[43,264,222],{"class":56},[43,266,204],{"class":197},[43,268,270,272,274,277,280,283,286],{"class":45,"line":269},28,[43,271,219],{"class":197},[43,273,246],{"class":60},[43,275,276],{"class":197},"]$Domain ",[43,278,279],{"class":60},"=",[43,281,282],{"class":197}," $",[43,284,285],{"class":56},"env:",[43,287,288],{"class":197},"USERDNSDOMAIN\n",[43,290,292],{"class":45,"line":291},29,[43,293,294],{"class":197},")\n",[43,296,298],{"class":45,"line":297},30,[43,299,191],{"emptyLinePlaceholder":190},[43,301,303,306],{"class":45,"line":302},31,[43,304,305],{"class":56},"Import-Module",[43,307,308],{"class":197}," GroupPolicy\n",[43,310,312,315,318,321,324,327,329,332,335],{"class":45,"line":311},32,[43,313,314],{"class":56},"New-Item",[43,316,317],{"class":60}," -",[43,319,320],{"class":197},"Path $OutputFolder ",[43,322,323],{"class":60},"-",[43,325,326],{"class":197},"ItemType Directory ",[43,328,323],{"class":60},[43,330,331],{"class":197},"Force ",[43,333,334],{"class":60},"|",[43,336,337],{"class":56}," Out-Null\n",[43,339,341],{"class":45,"line":340},33,[43,342,191],{"emptyLinePlaceholder":190},[43,344,346,349,351,354],{"class":45,"line":345},34,[43,347,348],{"class":197},"$maxBytes ",[43,350,279],{"class":60},[43,352,353],{"class":56}," 4",[43,355,356],{"class":60},"MB\n",[43,358,360,363,365,368,371,374,377,379,382,384],{"class":45,"line":359},35,[43,361,362],{"class":197},"$inventory ",[43,364,279],{"class":60},[43,366,367],{"class":60}," foreach",[43,369,370],{"class":197}," ($gpo ",[43,372,373],{"class":60},"in",[43,375,376],{"class":56}," Get-GPO",[43,378,317],{"class":60},[43,380,381],{"class":197},"All ",[43,383,323],{"class":60},[43,385,386],{"class":197},"Domain $Domain) {\n",[43,388,390,393,395,398,401,405,408],{"class":45,"line":389},36,[43,391,392],{"class":197},"    $safeName ",[43,394,279],{"class":60},[43,396,397],{"class":197}," $gpo.DisplayName ",[43,399,400],{"class":60},"-replace",[43,402,404],{"class":403},"sU2Wk"," '[\\\\\u002F:*?\"\u003C>|]'",[43,406,407],{"class":60},",",[43,409,410],{"class":403}," '_'\n",[43,412,414],{"class":45,"line":413},37,[43,415,416],{"class":49},"    # Display names aren't guaranteed unique, so the GUID keeps each file distinct.\n",[43,418,420,423,425,428,430,432,434,437,440,443,445,448,450,453,456],{"class":45,"line":419},38,[43,421,422],{"class":197},"    $xmlPath ",[43,424,279],{"class":60},[43,426,427],{"class":56}," Join-Path",[43,429,317],{"class":60},[43,431,320],{"class":197},[43,433,323],{"class":60},[43,435,436],{"class":197},"ChildPath ",[43,438,439],{"class":403},"\"",[43,441,442],{"class":197},"$safeName",[43,444,323],{"class":403},[43,446,447],{"class":60},"$",[43,449,225],{"class":403},[43,451,452],{"class":197},"$gpo.Id",[43,454,455],{"class":403},")",[43,457,458],{"class":403},".xml\"\n",[43,460,462],{"class":45,"line":461},39,[43,463,191],{"emptyLinePlaceholder":190},[43,465,467,470,472,475,477,480,482,485,487],{"class":45,"line":466},40,[43,468,469],{"class":56},"    Get-GPOReport",[43,471,317],{"class":60},[43,473,474],{"class":197},"Guid $gpo.Id ",[43,476,323],{"class":60},[43,478,479],{"class":197},"ReportType Xml ",[43,481,323],{"class":60},[43,483,484],{"class":197},"Domain $Domain ",[43,486,323],{"class":60},[43,488,489],{"class":197},"Path $xmlPath\n",[43,491,493,495,498,501,503,506,508,511,513],{"class":45,"line":492},41,[43,494,219],{"class":197},[43,496,497],{"class":60},"xml",[43,499,500],{"class":197},"]$report ",[43,502,279],{"class":60},[43,504,505],{"class":56}," Get-Content",[43,507,317],{"class":60},[43,509,510],{"class":197},"Path $xmlPath ",[43,512,323],{"class":60},[43,514,515],{"class":197},"Raw\n",[43,517,519],{"class":45,"line":518},42,[43,520,191],{"emptyLinePlaceholder":190},[43,522,524],{"class":45,"line":523},43,[43,525,526],{"class":49},"    # Each LinksTo element is one link (SOMPath is the OU or domain path).\n",[43,528,530,533,535,538],{"class":45,"line":529},44,[43,531,532],{"class":197},"    $links ",[43,534,279],{"class":60},[43,536,537],{"class":60}," @",[43,539,540],{"class":197},"($report.GPO.LinksTo)\n",[43,542,544,547,549,551,554,556,559,562,565,568,571,574],{"class":45,"line":543},45,[43,545,546],{"class":197},"    $enabledLinks ",[43,548,279],{"class":60},[43,550,537],{"class":60},[43,552,553],{"class":197},"($links ",[43,555,334],{"class":60},[43,557,558],{"class":56}," Where-Object",[43,560,561],{"class":197}," { ",[43,563,564],{"class":56},"$_",[43,566,567],{"class":197},".Enabled ",[43,569,570],{"class":60},"-eq",[43,572,573],{"class":403}," 'true'",[43,575,576],{"class":197}," })\n",[43,578,580,583,585,588,591,593],{"class":45,"line":579},46,[43,581,582],{"class":197},"    $size ",[43,584,279],{"class":60},[43,586,587],{"class":197}," (",[43,589,590],{"class":56},"Get-Item",[43,592,317],{"class":60},[43,594,595],{"class":197},"Path $xmlPath).Length\n",[43,597,599],{"class":45,"line":598},47,[43,600,191],{"emptyLinePlaceholder":190},[43,602,604,607,609],{"class":45,"line":603},48,[43,605,606],{"class":197},"    $candidate ",[43,608,279],{"class":60},[43,610,611],{"class":403}," 'Migrate or retire'\n",[43,613,615,618,621,623,626],{"class":45,"line":614},49,[43,616,617],{"class":60},"    if",[43,619,620],{"class":197}," ($enabledLinks.Count ",[43,622,570],{"class":60},[43,624,625],{"class":56}," 0",[43,627,628],{"class":197},") {\n",[43,630,632,635,637],{"class":45,"line":631},50,[43,633,634],{"class":197},"        $candidate ",[43,636,279],{"class":60},[43,638,639],{"class":403}," 'Unlinked: review for deletion'\n",[43,641,643,646,649,652,654,657],{"class":45,"line":642},51,[43,644,645],{"class":197},"    } ",[43,647,648],{"class":60},"elseif",[43,650,651],{"class":197}," ($gpo.GpoStatus ",[43,653,570],{"class":60},[43,655,656],{"class":403}," 'AllSettingsDisabled'",[43,658,628],{"class":197},[43,660,662,664,666],{"class":45,"line":661},52,[43,663,634],{"class":197},[43,665,279],{"class":60},[43,667,668],{"class":403}," 'All settings disabled'\n",[43,670,672],{"class":45,"line":671},53,[43,673,674],{"class":197},"    }\n",[43,676,678],{"class":45,"line":677},54,[43,679,191],{"emptyLinePlaceholder":190},[43,681,683,685,688,691,694],{"class":45,"line":682},55,[43,684,219],{"class":197},[43,686,687],{"class":60},"PSCustomObject",[43,689,690],{"class":197},"]",[43,692,693],{"class":60},"@",[43,695,696],{"class":197},"{\n",[43,698,700,703,705],{"class":45,"line":699},56,[43,701,702],{"class":197},"        Name             ",[43,704,279],{"class":60},[43,706,707],{"class":197}," $gpo.DisplayName\n",[43,709,711,714,716],{"class":45,"line":710},57,[43,712,713],{"class":197},"        Id               ",[43,715,279],{"class":60},[43,717,718],{"class":197}," $gpo.Id\n",[43,720,722,725,727],{"class":45,"line":721},58,[43,723,724],{"class":197},"        GpoStatus        ",[43,726,279],{"class":60},[43,728,729],{"class":197}," $gpo.GpoStatus\n",[43,731,733,736,738],{"class":45,"line":732},59,[43,734,735],{"class":197},"        ModificationTime ",[43,737,279],{"class":60},[43,739,740],{"class":197}," $gpo.ModificationTime\n",[43,742,744,747,749],{"class":45,"line":743},60,[43,745,746],{"class":197},"        LinkCount        ",[43,748,279],{"class":60},[43,750,751],{"class":197}," $links.Count\n",[43,753,755,758,760],{"class":45,"line":754},61,[43,756,757],{"class":197},"        EnabledLinks     ",[43,759,279],{"class":60},[43,761,762],{"class":197}," $enabledLinks.Count\n",[43,764,766,769,771,774,776,779,781,783,786,789],{"class":45,"line":765},62,[43,767,768],{"class":197},"        LinkedTo         ",[43,770,279],{"class":60},[43,772,773],{"class":197}," ($enabledLinks ",[43,775,334],{"class":60},[43,777,778],{"class":56}," ForEach-Object",[43,780,561],{"class":197},[43,782,564],{"class":56},[43,784,785],{"class":197},".SOMPath }) ",[43,787,788],{"class":60},"-join",[43,790,791],{"class":403}," '; '\n",[43,793,795,798,800,803,806,809,812,815,818,820],{"class":45,"line":794},63,[43,796,797],{"class":197},"        ReportKB         ",[43,799,279],{"class":60},[43,801,802],{"class":197}," [",[43,804,805],{"class":60},"math",[43,807,808],{"class":197},"]::Round($size ",[43,810,811],{"class":60},"\u002F",[43,813,814],{"class":56}," 1",[43,816,817],{"class":60},"KB,",[43,819,814],{"class":56},[43,821,294],{"class":197},[43,823,825,828,830,833,836],{"class":45,"line":824},64,[43,826,827],{"class":197},"        OverImportLimit  ",[43,829,279],{"class":60},[43,831,832],{"class":197}," $size ",[43,834,835],{"class":60},"-gt",[43,837,838],{"class":197}," $maxBytes\n",[43,840,842,845,847],{"class":45,"line":841},65,[43,843,844],{"class":197},"        Candidate        ",[43,846,279],{"class":60},[43,848,849],{"class":197}," $candidate\n",[43,851,853],{"class":45,"line":852},66,[43,854,674],{"class":197},[43,856,858],{"class":45,"line":857},67,[43,859,860],{"class":197},"}\n",[43,862,864],{"class":45,"line":863},68,[43,865,191],{"emptyLinePlaceholder":190},[43,867,869,872,874,876,878,880,882,884],{"class":45,"line":868},69,[43,870,871],{"class":197},"$csvPath ",[43,873,279],{"class":60},[43,875,427],{"class":56},[43,877,317],{"class":60},[43,879,320],{"class":197},[43,881,323],{"class":60},[43,883,436],{"class":197},[43,885,886],{"class":403},"'gpo-inventory.csv'\n",[43,888,890,892,894,897,899,902,904,907,909,912,914,917,919,922,924],{"class":45,"line":889},70,[43,891,362],{"class":197},[43,893,334],{"class":60},[43,895,896],{"class":56}," Sort-Object",[43,898,317],{"class":60},[43,900,901],{"class":197},"Property EnabledLinks",[43,903,407],{"class":60},[43,905,906],{"class":197}," Name ",[43,908,334],{"class":60},[43,910,911],{"class":56}," Export-Csv",[43,913,317],{"class":60},[43,915,916],{"class":197},"Path $csvPath ",[43,918,323],{"class":60},[43,920,921],{"class":197},"NoTypeInformation ",[43,923,323],{"class":60},[43,925,926],{"class":197},"Encoding utf8\n",[43,928,930,932,934,937,939,942,944,947,949,952,954,957,959,962,964],{"class":45,"line":929},71,[43,931,362],{"class":197},[43,933,334],{"class":60},[43,935,936],{"class":56}," Group-Object",[43,938,317],{"class":60},[43,940,941],{"class":197},"Property Candidate ",[43,943,334],{"class":60},[43,945,946],{"class":56}," Select-Object",[43,948,317],{"class":60},[43,950,951],{"class":197},"Property Name",[43,953,407],{"class":60},[43,955,956],{"class":197}," Count ",[43,958,334],{"class":60},[43,960,961],{"class":56}," Format-Table",[43,963,317],{"class":60},[43,965,966],{"class":197},"AutoSize\n",[43,968,970,973,976,978,980,982,984,987,990,993,996],{"class":45,"line":969},72,[43,971,972],{"class":56},"Write-Host",[43,974,975],{"class":403}," \"Wrote ",[43,977,447],{"class":60},[43,979,225],{"class":403},[43,981,693],{"class":60},[43,983,225],{"class":403},[43,985,986],{"class":197},"$inventory",[43,988,989],{"class":403},").Count)",[43,991,992],{"class":403}," reports and ",[43,994,995],{"class":197},"$csvPath",[43,997,998],{"class":403},"\"\n",[11,1000,1001],{},"Typical console output:",[34,1003,1008],{"className":1004,"code":1006,"language":1007,"meta":39},[1005],"language-text","Name                          Count\n----                          -----\nMigrate or retire                58\nUnlinked: review for deletion    23\nAll settings disabled             6\n\nWrote 87 reports and C:\\GpoExport\\gpo-inventory.csv\n","text",[29,1009,1006],{"__ignoreMap":39},[11,1011,1012,1013,1016,1017,1020,1021,1024],{},"The ",[29,1014,1015],{},"LinksTo",", ",[29,1018,1019],{},"SOMPath"," and ",[29,1022,1023],{},"Enabled"," element names come from the GPMC XML report format; open one exported file and check them before you trust the counts. The CSV is where the real work starts: every row in the \"Migrate or retire\" bucket gets an owner and a decision before anything is built in Intune.",[18,1026,1028],{"id":1027},"let-group-policy-analytics-do-the-first-pass","Let Group Policy analytics do the first pass",[11,1030,1031,1032,1036,1037,1040,1041,1044],{},"Intune's Group Policy analytics (",[1033,1034,1035],"strong",{},"Devices > Manage devices > Group Policy analytics > Import",") takes those XML files and tells you, per GPO, what percentage of settings has an MDM equivalent. Microsoft documents GPMC's ",[1033,1038,1039],{},"Save Report"," as XML as the export method; if a file produced by ",[29,1042,1043],{},"Get-GPOReport"," won't import, re-save that GPO from GPMC. The rules worth knowing before you start:",[1046,1047,1048,1052,1067,1077,1084],"ul",{},[1049,1050,1051],"li",{},"A single GPO XML must be under 4 MB and correctly Unicode-encoded, or the import fails. The inventory script flags oversize files.",[1049,1053,1054,1055,1058,1059,1062,1063,1066],{},"You can import several files at once. The list view shows ",[1033,1056,1057],{},"MDM Support"," (the percentage), ",[1033,1060,1061],{},"Unknown Settings"," (settings in CSPs the tool can't parse), and ",[1033,1064,1065],{},"Targeted in AD",", which says whether the GPO is linked to an OU.",[1049,1068,1069,1070,1020,1073,1076],{},"Drilling into a GPO shows each setting's ",[1033,1071,1072],{},"CSP Name",[1033,1074,1075],{},"CSP Mapping",", which is the OMA-URI path. That column is useful even when you don't use the migration feature, because it hands you the exact path for a custom profile.",[1049,1078,1079,1080,1083],{},"The migration readiness report (",[1033,1081,1082],{},"Reports > Device management > Group policy analytics",") sorts settings into ready for migration, not supported, and deprecated.",[1049,1085,1086],{},"The parser covers the Policy, PassportForWork, BitLocker, Firewall and AppLocker CSPs plus Group Policy Preferences. Known issue: only English-language non-ADMX settings are analyzed correctly, so a GPO authored in another language reports a misleading percentage.",[11,1088,1012,1089,1092],{},[1033,1090,1091],{},"Migrate"," button then builds a Settings catalog profile from the settings you tick. Microsoft calls it best effort, and the details matter: AppLocker and firewall settings can't be migrated this way (build those in Endpoint security), some older Office and Chrome settings map to a newer equivalent rather than the same setting, and if two imported GPOs set the same setting to different values, the wizard stops with \"Conflicts are detected for the following settings\" until you pick one.",[18,1094,1096],{"id":1095},"settings-catalog-versus-custom-oma-uri","Settings catalog versus custom OMA-URI",[11,1098,1099,1100,1103,1104,1109],{},"Once you know what needs to move, most of it maps onto the Settings catalog, which covers most of what a configuration profile can express. A few things have their own policy types instead: security baselines, Windows Update rings, and BitLocker (under ",[1033,1101,1102],{},"Endpoint security > Disk encryption","). The catalog covers more ground every release, and I'd always rather use it than hand-roll a custom OMA-URI profile, because Microsoft documents and tests the catalog paths and you're on your own with a raw CSP. The friction shows up in the long tail: printer deployment logic, application-specific registry keys tied to a piece of line-of-business software, and login scripts doing things GPO could do natively but nobody ever moved off a script. Those need Win32 app deployments, PowerShell scripts or Remediations run through Intune, or in a few cases just get retired because the thing they configured stopped mattering years ago. If a login script really was a repair job, a Remediations detect and remediate pair is usually the better fit; the ",[1105,1106,1108],"a",{"href":1107},"\u002F2025\u002F09\u002F10\u002Fpowershell-intune-remediation-script-for-stuck-bitlocker-encryption\u002F","BitLocker remediation post"," shows the shape of one.",[18,1111,1113],{"id":1112},"running-both-in-parallel-is-not-optional","Running both in parallel is not optional",[11,1115,1116],{},"I've never seen a clean cutover work, and I stopped trying to force one. Two different parallel models get lumped together here, and it's worth being precise:",[1046,1118,1119,1125],{},[1049,1120,1121,1124],{},[1033,1122,1123],{},"Co-management"," is Configuration Manager and Intune managing the same device, with workloads moved one at a time: compliance policies, Windows Update policies, resource access, Endpoint Protection, device configuration, Office Click-to-Run apps and client apps. Each workload has a slider, and pilot collections let you move a subset first. This is the cleanest way to shift ownership if you run ConfigMgr.",[1049,1126,1127,1130],{},[1033,1128,1129],{},"Group Policy plus Intune"," on hybrid-joined devices has no slider. Both engines apply whatever they're given, so ownership is something you enforce yourself, setting area by setting area.",[11,1132,1133,1134,1138],{},"Either way the order I use is the same: Windows Update first (low risk, easy to verify, and Update rings replace a WSUS GPO cleanly), then device restrictions and security settings, then the application and script-based settings last. Each area gets its own pilot group, verify, expand cycle. After moving an area, forcing a check-in on the pilot group shortens the verify step considerably; the ",[1105,1135,1137],{"href":1136},"\u002F2025\u002F10\u002F22\u002Fpowershell-intune-force-a-compliance-policy-re-evaluation-fleet-wide\u002F","fleet-wide sync script"," does that through Graph. Rushing this is how you end up with conflicting policies fighting silently, which is worse than either source acting alone, because troubleshooting means checking two consoles instead of one.",[18,1140,1142],{"id":1141},"conflict-resolution-and-the-settings-youll-fight-over","Conflict resolution and the settings you'll fight over",[11,1144,1145,1146,1149],{},"The earlier version of this section said Windows generally lets GPO win. That's not what Microsoft documents. When the same setting is configured by both Group Policy and MDM, and the setting isn't covered by the ",[29,1147,1148],{},"MDMWinsOverGP"," policy, Microsoft's words are that \"there will be a race condition and no guarantee which one wins.\" Which is worse than a predictable loser, and it explains the afternoons lost to a setting that applies on one reboot and not the next.",[11,1151,1152,1154,1155,1158],{},[29,1153,1148],{}," (ControlPolicyConflict in the Policy CSP, Windows 10 1803 and later) changes that for settings in scope. With it set to ",[29,1156,1157],{},"1",", any MDM policy that has an equivalent Group Policy blocks the GP version. I deploy it as a custom OMA-URI setting to the same pilot groups as the first migrated profiles:",[1160,1161,1162,1175],"table",{},[1163,1164,1165],"thead",{},[1166,1167,1168,1172],"tr",{},[1169,1170,1171],"th",{},"Field",[1169,1173,1174],{},"Value",[1176,1177,1178,1189,1197],"tbody",{},[1166,1179,1180,1184],{},[1181,1182,1183],"td",{},"OMA-URI",[1181,1185,1186],{},[29,1187,1188],{},".\u002FDevice\u002FVendor\u002FMSFT\u002FPolicy\u002FConfig\u002FControlPolicyConflict\u002FMDMWinsOverGP",[1166,1190,1191,1194],{},[1181,1192,1193],{},"Data type",[1181,1195,1196],{},"Integer",[1166,1198,1199,1201],{},[1181,1200,1174],{},[1181,1202,1203,1205,1206],{},[29,1204,1157],{}," (MDM policy is used, GP policy is blocked); default ",[29,1207,1208],{},"0",[11,1210,1211],{},"The limits are the important part. It applies only to policies in the Policy CSP. Settings defined in other CSPs (Microsoft's example is the Defender CSP) aren't covered, so for those the guidance is simply not to configure the same setting in both places. The MDM Diagnostic report lists which GP settings were blocked because an MDM equivalent exists, which is the quickest way to prove what's happening on a disputed device.",[11,1213,1214,1215,1218,1219,1221],{},"To gather that evidence in one pass, I run this on the device. It produces the Group Policy result report, the MDM diagnostics archive, and a CSV of the values MDM has delivered under ",[29,1216,1217],{},"HKLM\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device",", along with whether ",[29,1220,1148],{}," has arrived:",[34,1223,1225],{"className":36,"code":1224,"language":38,"meta":39,"style":39},"\u003C#\n.SYNOPSIS\n    Collects Group Policy and MDM policy evidence from one Windows device.\n.DESCRIPTION\n    Runs gpresult for the computer scope (HTML), runs mdmdiagnosticstool to\n    produce the MDM diagnostics archive, lists the MDM-delivered policy values\n    under HKLM:\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device, and reports\n    whether ControlPolicyConflict\u002FMDMWinsOverGP is present.\n.PARAMETER OutputFolder\n    Folder for the reports. Defaults to C:\\Users\\Public\\Documents\\PolicyEvidence.\n.EXAMPLE\n    .\\Get-PolicySourceEvidence.ps1\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2026-04-01)\n    Requires: Elevated PowerShell on the device.\n#>\n\n[CmdletBinding()]\nparam (\n    [Parameter()]\n    [string]$OutputFolder = \"C:\\Users\\Public\\Documents\\PolicyEvidence\"\n)\n\nNew-Item -Path $OutputFolder -ItemType Directory -Force | Out-Null\n\n# Group Policy resultant set for the computer.\n$gpReport = Join-Path -Path $OutputFolder -ChildPath \"gpresult-computer.html\"\n& gpresult.exe \u002Fscope computer \u002Fh $gpReport \u002Ff | Out-Null\n\n# MDM diagnostics archive (includes MDMDiagHtmlReport.html and the admin event log).\n$mdmZip = Join-Path -Path $OutputFolder -ChildPath \"MDMDiagReport.zip\"\n& mdmdiagnosticstool.exe -area \"DeviceEnrollment;DeviceProvisioning\" -zip $mdmZip | Out-Null\n\n# Values MDM has delivered, one row per area and setting.\n$root = \"HKLM:\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device\"\n$rows = foreach ($area in Get-ChildItem -Path $root -ErrorAction SilentlyContinue) {\n    $values = Get-ItemProperty -Path $area.PSPath\n    foreach ($property in $values.PSObject.Properties) {\n        if ($property.Name -notlike 'PS*') {\n            [PSCustomObject]@{\n                Area    = $area.PSChildName\n                Setting = $property.Name\n                Value   = $property.Value\n            }\n        }\n    }\n}\n$csv = Join-Path -Path $OutputFolder -ChildPath \"mdm-policies.csv\"\n$rows | Export-Csv -Path $csv -NoTypeInformation -Encoding utf8\n\n$conflict = Get-ItemProperty -Path \"$root\\ControlPolicyConflict\" -Name \"MDMWinsOverGP\" -ErrorAction SilentlyContinue\n$mdmWins = if ($conflict) { $conflict.MDMWinsOverGP } else { \"not delivered\" }\n\nWrite-Host \"MDM policy values : $(@($rows).Count) in $(@($rows | Select-Object -Property Area -Unique).Count) areas -> $csv\"\nWrite-Host \"MDMWinsOverGP     : $mdmWins\"\nWrite-Host \"gpresult          : $gpReport\"\nWrite-Host \"MDM diagnostics   : $mdmZip\"\n",[29,1226,1227,1231,1237,1242,1248,1253,1258,1263,1268,1276,1281,1287,1292,1298,1302,1306,1311,1315,1319,1327,1333,1341,1355,1359,1363,1383,1387,1392,1412,1440,1444,1449,1469,1493,1497,1502,1512,1539,1554,1567,1583,1596,1606,1616,1626,1631,1636,1640,1644,1664,1685,1689,1724,1748,1752,1808,1820,1832],{"__ignoreMap":39},[43,1228,1229],{"class":45,"line":46},[43,1230,50],{"class":49},[43,1232,1233,1235],{"class":45,"line":53},[43,1234,57],{"class":56},[43,1236,61],{"class":60},[43,1238,1239],{"class":45,"line":64},[43,1240,1241],{"class":49},"    Collects Group Policy and MDM policy evidence from one Windows device.\n",[43,1243,1244,1246],{"class":45,"line":70},[43,1245,57],{"class":56},[43,1247,75],{"class":60},[43,1249,1250],{"class":45,"line":78},[43,1251,1252],{"class":49},"    Runs gpresult for the computer scope (HTML), runs mdmdiagnosticstool to\n",[43,1254,1255],{"class":45,"line":84},[43,1256,1257],{"class":49},"    produce the MDM diagnostics archive, lists the MDM-delivered policy values\n",[43,1259,1260],{"class":45,"line":90},[43,1261,1262],{"class":49},"    under HKLM:\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device, and reports\n",[43,1264,1265],{"class":45,"line":96},[43,1266,1267],{"class":49},"    whether ControlPolicyConflict\u002FMDMWinsOverGP is present.\n",[43,1269,1270,1272,1274],{"class":45,"line":102},[43,1271,57],{"class":56},[43,1273,113],{"class":60},[43,1275,116],{"class":60},[43,1277,1278],{"class":45,"line":108},[43,1279,1280],{"class":49},"    Folder for the reports. Defaults to C:\\Users\\Public\\Documents\\PolicyEvidence.\n",[43,1282,1283,1285],{"class":45,"line":119},[43,1284,57],{"class":56},[43,1286,146],{"class":60},[43,1288,1289],{"class":45,"line":125},[43,1290,1291],{"class":49},"    .\\Get-PolicySourceEvidence.ps1\n",[43,1293,1294,1296],{"class":45,"line":135},[43,1295,57],{"class":56},[43,1297,160],{"class":60},[43,1299,1300],{"class":45,"line":141},[43,1301,166],{"class":49},[43,1303,1304],{"class":45,"line":149},[43,1305,172],{"class":49},[43,1307,1308],{"class":45,"line":155},[43,1309,1310],{"class":49},"    Requires: Elevated PowerShell on the device.\n",[43,1312,1313],{"class":45,"line":163},[43,1314,184],{"class":49},[43,1316,1317],{"class":45,"line":169},[43,1318,191],{"emptyLinePlaceholder":190},[43,1320,1321,1323,1325],{"class":45,"line":175},[43,1322,198],{"class":197},[43,1324,201],{"class":56},[43,1326,204],{"class":197},[43,1328,1329,1331],{"class":45,"line":181},[43,1330,210],{"class":60},[43,1332,213],{"class":197},[43,1334,1335,1337,1339],{"class":45,"line":187},[43,1336,219],{"class":197},[43,1338,222],{"class":56},[43,1340,204],{"class":197},[43,1342,1343,1345,1347,1350,1352],{"class":45,"line":194},[43,1344,219],{"class":197},[43,1346,246],{"class":60},[43,1348,1349],{"class":197},"]$OutputFolder ",[43,1351,279],{"class":60},[43,1353,1354],{"class":403}," \"C:\\Users\\Public\\Documents\\PolicyEvidence\"\n",[43,1356,1357],{"class":45,"line":207},[43,1358,294],{"class":197},[43,1360,1361],{"class":45,"line":216},[43,1362,191],{"emptyLinePlaceholder":190},[43,1364,1365,1367,1369,1371,1373,1375,1377,1379,1381],{"class":45,"line":241},[43,1366,314],{"class":56},[43,1368,317],{"class":60},[43,1370,320],{"class":197},[43,1372,323],{"class":60},[43,1374,326],{"class":197},[43,1376,323],{"class":60},[43,1378,331],{"class":197},[43,1380,334],{"class":60},[43,1382,337],{"class":56},[43,1384,1385],{"class":45,"line":255},[43,1386,191],{"emptyLinePlaceholder":190},[43,1388,1389],{"class":45,"line":260},[43,1390,1391],{"class":49},"# Group Policy resultant set for the computer.\n",[43,1393,1394,1397,1399,1401,1403,1405,1407,1409],{"class":45,"line":269},[43,1395,1396],{"class":197},"$gpReport ",[43,1398,279],{"class":60},[43,1400,427],{"class":56},[43,1402,317],{"class":60},[43,1404,320],{"class":197},[43,1406,323],{"class":60},[43,1408,436],{"class":197},[43,1410,1411],{"class":403},"\"gpresult-computer.html\"\n",[43,1413,1414,1417,1420,1423,1426,1428,1431,1433,1436,1438],{"class":45,"line":291},[43,1415,1416],{"class":60},"&",[43,1418,1419],{"class":56}," gpresult.exe",[43,1421,1422],{"class":60}," \u002F",[43,1424,1425],{"class":197},"scope computer ",[43,1427,811],{"class":60},[43,1429,1430],{"class":197},"h $gpReport ",[43,1432,811],{"class":60},[43,1434,1435],{"class":197},"f ",[43,1437,334],{"class":60},[43,1439,337],{"class":56},[43,1441,1442],{"class":45,"line":297},[43,1443,191],{"emptyLinePlaceholder":190},[43,1445,1446],{"class":45,"line":302},[43,1447,1448],{"class":49},"# MDM diagnostics archive (includes MDMDiagHtmlReport.html and the admin event log).\n",[43,1450,1451,1454,1456,1458,1460,1462,1464,1466],{"class":45,"line":311},[43,1452,1453],{"class":197},"$mdmZip ",[43,1455,279],{"class":60},[43,1457,427],{"class":56},[43,1459,317],{"class":60},[43,1461,320],{"class":197},[43,1463,323],{"class":60},[43,1465,436],{"class":197},[43,1467,1468],{"class":403},"\"MDMDiagReport.zip\"\n",[43,1470,1471,1473,1476,1478,1481,1484,1486,1489,1491],{"class":45,"line":340},[43,1472,1416],{"class":60},[43,1474,1475],{"class":56}," mdmdiagnosticstool.exe",[43,1477,317],{"class":60},[43,1479,1480],{"class":197},"area ",[43,1482,1483],{"class":403},"\"DeviceEnrollment;DeviceProvisioning\"",[43,1485,317],{"class":60},[43,1487,1488],{"class":197},"zip $mdmZip ",[43,1490,334],{"class":60},[43,1492,337],{"class":56},[43,1494,1495],{"class":45,"line":345},[43,1496,191],{"emptyLinePlaceholder":190},[43,1498,1499],{"class":45,"line":359},[43,1500,1501],{"class":49},"# Values MDM has delivered, one row per area and setting.\n",[43,1503,1504,1507,1509],{"class":45,"line":389},[43,1505,1506],{"class":197},"$root ",[43,1508,279],{"class":60},[43,1510,1511],{"class":403}," \"HKLM:\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device\"\n",[43,1513,1514,1517,1519,1521,1524,1526,1529,1531,1534,1536],{"class":45,"line":413},[43,1515,1516],{"class":197},"$rows ",[43,1518,279],{"class":60},[43,1520,367],{"class":60},[43,1522,1523],{"class":197}," ($area ",[43,1525,373],{"class":60},[43,1527,1528],{"class":56}," Get-ChildItem",[43,1530,317],{"class":60},[43,1532,1533],{"class":197},"Path $root ",[43,1535,323],{"class":60},[43,1537,1538],{"class":197},"ErrorAction SilentlyContinue) {\n",[43,1540,1541,1544,1546,1549,1551],{"class":45,"line":419},[43,1542,1543],{"class":197},"    $values ",[43,1545,279],{"class":60},[43,1547,1548],{"class":56}," Get-ItemProperty",[43,1550,317],{"class":60},[43,1552,1553],{"class":197},"Path $area.PSPath\n",[43,1555,1556,1559,1562,1564],{"class":45,"line":461},[43,1557,1558],{"class":60},"    foreach",[43,1560,1561],{"class":197}," ($property ",[43,1563,373],{"class":60},[43,1565,1566],{"class":197}," $values.PSObject.Properties) {\n",[43,1568,1569,1572,1575,1578,1581],{"class":45,"line":466},[43,1570,1571],{"class":60},"        if",[43,1573,1574],{"class":197}," ($property.Name ",[43,1576,1577],{"class":60},"-notlike",[43,1579,1580],{"class":403}," 'PS*'",[43,1582,628],{"class":197},[43,1584,1585,1588,1590,1592,1594],{"class":45,"line":492},[43,1586,1587],{"class":197},"            [",[43,1589,687],{"class":60},[43,1591,690],{"class":197},[43,1593,693],{"class":60},[43,1595,696],{"class":197},[43,1597,1598,1601,1603],{"class":45,"line":518},[43,1599,1600],{"class":197},"                Area    ",[43,1602,279],{"class":60},[43,1604,1605],{"class":197}," $area.PSChildName\n",[43,1607,1608,1611,1613],{"class":45,"line":523},[43,1609,1610],{"class":197},"                Setting ",[43,1612,279],{"class":60},[43,1614,1615],{"class":197}," $property.Name\n",[43,1617,1618,1621,1623],{"class":45,"line":529},[43,1619,1620],{"class":197},"                Value   ",[43,1622,279],{"class":60},[43,1624,1625],{"class":197}," $property.Value\n",[43,1627,1628],{"class":45,"line":543},[43,1629,1630],{"class":197},"            }\n",[43,1632,1633],{"class":45,"line":579},[43,1634,1635],{"class":197},"        }\n",[43,1637,1638],{"class":45,"line":598},[43,1639,674],{"class":197},[43,1641,1642],{"class":45,"line":603},[43,1643,860],{"class":197},[43,1645,1646,1649,1651,1653,1655,1657,1659,1661],{"class":45,"line":614},[43,1647,1648],{"class":197},"$csv ",[43,1650,279],{"class":60},[43,1652,427],{"class":56},[43,1654,317],{"class":60},[43,1656,320],{"class":197},[43,1658,323],{"class":60},[43,1660,436],{"class":197},[43,1662,1663],{"class":403},"\"mdm-policies.csv\"\n",[43,1665,1666,1668,1670,1672,1674,1677,1679,1681,1683],{"class":45,"line":631},[43,1667,1516],{"class":197},[43,1669,334],{"class":60},[43,1671,911],{"class":56},[43,1673,317],{"class":60},[43,1675,1676],{"class":197},"Path $csv ",[43,1678,323],{"class":60},[43,1680,921],{"class":197},[43,1682,323],{"class":60},[43,1684,926],{"class":197},[43,1686,1687],{"class":45,"line":642},[43,1688,191],{"emptyLinePlaceholder":190},[43,1690,1691,1694,1696,1698,1700,1703,1705,1708,1711,1713,1716,1719,1721],{"class":45,"line":661},[43,1692,1693],{"class":197},"$conflict ",[43,1695,279],{"class":60},[43,1697,1548],{"class":56},[43,1699,317],{"class":60},[43,1701,1702],{"class":197},"Path ",[43,1704,439],{"class":403},[43,1706,1707],{"class":197},"$root",[43,1709,1710],{"class":403},"\\ControlPolicyConflict\"",[43,1712,317],{"class":60},[43,1714,1715],{"class":197},"Name ",[43,1717,1718],{"class":403},"\"MDMWinsOverGP\"",[43,1720,317],{"class":60},[43,1722,1723],{"class":197},"ErrorAction SilentlyContinue\n",[43,1725,1726,1729,1731,1734,1737,1740,1742,1745],{"class":45,"line":671},[43,1727,1728],{"class":197},"$mdmWins ",[43,1730,279],{"class":60},[43,1732,1733],{"class":60}," if",[43,1735,1736],{"class":197}," ($conflict) { $conflict.MDMWinsOverGP } ",[43,1738,1739],{"class":60},"else",[43,1741,561],{"class":197},[43,1743,1744],{"class":403},"\"not delivered\"",[43,1746,1747],{"class":197}," }\n",[43,1749,1750],{"class":45,"line":677},[43,1751,191],{"emptyLinePlaceholder":190},[43,1753,1754,1756,1759,1761,1763,1765,1767,1770,1772,1775,1777,1779,1781,1783,1785,1788,1790,1792,1795,1797,1800,1803,1806],{"class":45,"line":682},[43,1755,972],{"class":56},[43,1757,1758],{"class":403}," \"MDM policy values : ",[43,1760,447],{"class":60},[43,1762,225],{"class":403},[43,1764,693],{"class":60},[43,1766,225],{"class":403},[43,1768,1769],{"class":197},"$rows",[43,1771,989],{"class":403},[43,1773,1774],{"class":403}," in ",[43,1776,447],{"class":60},[43,1778,225],{"class":403},[43,1780,693],{"class":60},[43,1782,225],{"class":403},[43,1784,1769],{"class":197},[43,1786,1787],{"class":60}," |",[43,1789,946],{"class":56},[43,1791,317],{"class":60},[43,1793,1794],{"class":403},"Property Area ",[43,1796,323],{"class":60},[43,1798,1799],{"class":403},"Unique).Count)",[43,1801,1802],{"class":403}," areas -> ",[43,1804,1805],{"class":197},"$csv",[43,1807,998],{"class":403},[43,1809,1810,1812,1815,1818],{"class":45,"line":699},[43,1811,972],{"class":56},[43,1813,1814],{"class":403}," \"MDMWinsOverGP     : ",[43,1816,1817],{"class":197},"$mdmWins",[43,1819,998],{"class":403},[43,1821,1822,1824,1827,1830],{"class":45,"line":710},[43,1823,972],{"class":56},[43,1825,1826],{"class":403}," \"gpresult          : ",[43,1828,1829],{"class":197},"$gpReport",[43,1831,998],{"class":403},[43,1833,1834,1836,1839,1842],{"class":45,"line":721},[43,1835,972],{"class":56},[43,1837,1838],{"class":403}," \"MDM diagnostics   : ",[43,1840,1841],{"class":197},"$mdmZip",[43,1843,998],{"class":403},[11,1845,1846,1847,1850],{},"Compare the areas in ",[29,1848,1849],{},"mdm-policies.csv"," with the computer settings in the gpresult report. Any setting configured in both, outside the Policy CSP, is one you need to remove from one side.",[18,1852,1854],{"id":1853},"what-made-the-difference-in-practice","What made the difference in practice",[11,1856,1857],{},"The migrations that went smoothly were the ones where I resisted the urge to modernize everything at once. Moving a legacy GPO setting into Intune exactly as-is, verifying it, and only then considering whether a cloud-native equivalent (Windows Update rings instead of a WSUS GPO, for instance) is actually a better fit kept the risk contained to one variable at a time. The migrations that went badly were the ones where \"let's finally fix this while we're in there\" turned one change into three, and when something broke nobody could say which of the three caused it.",[11,1859,1860],{},"The last step is the one people skip: once an area is fully owned by Intune and verified, unlink the GPO rather than leaving it in place \"just in case.\" A GPO that still applies is a second source of truth, and the whole point was to have one.",[18,1862,1864],{"id":1863},"references","References",[1046,1866,1867,1875,1882,1889,1895,1902,1909],{},[1049,1868,1869],{},[1105,1870,1874],{"href":1871,"rel":1872},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fintune\u002Fdevice-configuration\u002Fimport-group-policy-analytics",[1873],"nofollow","Import and analyze group policies with Group Policy analytics",[1049,1876,1877],{},[1105,1878,1881],{"href":1879,"rel":1880},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fintune\u002Fdevice-configuration\u002Fmigrate-group-policy",[1873],"Migrate imported GPOs to a Settings catalog policy",[1049,1883,1884],{},[1105,1885,1888],{"href":1886,"rel":1887},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fclient-management\u002Fmdm\u002Fpolicy-csp-controlpolicyconflict",[1873],"ControlPolicyConflict Policy CSP (MDMWinsOverGP)",[1049,1890,1891],{},[1105,1892,1043],{"href":1893,"rel":1894},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fgrouppolicy\u002Fget-gporeport",[1873],[1049,1896,1897],{},[1105,1898,1901],{"href":1899,"rel":1900},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fintune\u002Fconfigmgr\u002Fcomanage\u002Fworkloads",[1873],"Co-management workloads",[1049,1903,1904],{},[1105,1905,1908],{"href":1906,"rel":1907},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fclient-management\u002Fmdm-collect-logs",[1873],"Collect MDM logs (mdmdiagnosticstool)",[1049,1910,1911],{},[1105,1912,1915],{"href":1913,"rel":1914},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fadministration\u002Fwindows-commands\u002Fgpresult",[1873],"gpresult",[1917,1918,1919],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":39,"searchDepth":53,"depth":53,"links":1921},[1922,1923,1924,1925,1926,1927,1928],{"id":20,"depth":53,"text":21},{"id":1027,"depth":53,"text":1028},{"id":1095,"depth":53,"text":1096},{"id":1112,"depth":53,"text":1113},{"id":1141,"depth":53,"text":1142},{"id":1853,"depth":53,"text":1854},{"id":1863,"depth":53,"text":1864},"techcolumnist",[1931,1932],"engineering","strategy","2026-04-01T14:00:00Z","Moving a Windows estate from Group Policy to Intune: GPO inventory script, Group Policy analytics, Settings catalog migration, MDMWinsOverGP and conflict checks.","md",false,null,{},"\u002Fblog\u002F2026\u002F04\u002F01\u002Fintune-migrating-from-group-policy-to-cloud-native-endpoint-management",{"title":6,"description":1934},[1929],"blog\u002F2026\u002F04\u002F01\u002Fintune-migrating-from-group-policy-to-cloud-native-endpoint-management",[1944,1945,1946,1947],"intune","gpo","windows","active-directory","\u002F2026\u002F04\u002F01\u002Fintune-migrating-from-group-policy-to-cloud-native-endpoint-management\u002F","lF7weYD5CGOnQlnxdL8VlqUplJq4fx1qefAuJkoDaO0",{"title":1951,"description":1952,"date":1953,"url":1954,"categories":1955,"tags":1956,"image":1937,"readingTime":96,"canonical":1929,"sites":1957,"series":1937,"seriesOrder":1937},"Intune: Autopilot Provisioning Failures and How to Actually Debug Them","Debugging Windows Autopilot failures from the evidence: documented error codes, event IDs, ESP tracking and timeouts, log collection, and triage scripts for device and Graph.","2026-04-08T14:00:00Z","\u002F2026\u002F04\u002F08\u002Fintune-autopilot-provisioning-failures-and-how-to-actually-debug-them\u002F",[1931],[1944,1946],[1929],{"title":1959,"description":1960,"date":1961,"url":1962,"categories":1963,"tags":1964,"image":1937,"readingTime":84,"canonical":1929,"sites":1967,"series":1937,"seriesOrder":1937},"Talos Linux: What Immutable Infrastructure Buys You in Production","Where an immutable, API-managed OS pays off under Kubernetes and where it bites: drift, upgrades, try-mode config changes, and debugging without SSH.","2026-03-25T14:00:00Z","\u002F2026\u002F03\u002F25\u002Ftalos-linux-what-immutable-infrastructure-actually-buys-you-in-production\u002F",[1931,1932],[1965,1966],"talos","kubernetes",[1929],[1969,1978,1987],{"title":1970,"description":1971,"date":1972,"url":1973,"categories":1974,"tags":1975,"image":1937,"readingTime":78,"canonical":1929,"sites":1977,"series":1937,"seriesOrder":1937},"Windows Management: A Discovery Inventory Nobody Maintains by Hand","Why a self-refreshing Windows inventory built from AD and CIM discovery outlasts a spreadsheet, with the sweep script, staleness report and schedule.","2026-09-02T14:00:00Z","\u002F2026\u002F09\u002F02\u002Fwindows-management-building-a-discovery-inventory-nobody-has-to-maintain-by-hand\u002F",[1931,1932],[1976,1946,1947],"discovery",[1929],{"title":1979,"description":1980,"date":1981,"url":1982,"categories":1983,"tags":1984,"image":1937,"readingTime":90,"canonical":1929,"sites":1986,"series":1937,"seriesOrder":1937},"Windows Server: Disabling IPv6 Company-Wide — What Actually Broke","Field notes on disabling IPv6 across a Windows Server estate: what Microsoft says, what breaks, why prefer-IPv4 (0x20) beats 0xFF, and an audit script.","2026-06-24T14:00:00Z","\u002F2026\u002F06\u002F24\u002Fwindows-server-disabling-ipv6-company-wide-what-actually-broke\u002F",[1931],[1946,1985,1945],"ipv6",[1929],{"title":1988,"description":1989,"date":1990,"url":1991,"categories":1992,"tags":1993,"image":1937,"readingTime":96,"canonical":1929,"sites":1996,"series":1937,"seriesOrder":1937},"Windows 11: A Debloat and Hardening Baseline for New Deployments","A repeatable Windows 11 baseline: policy-based app removal, Microsoft security baselines, BitLocker, Defender and ASR settings, plus a fleet audit script.","2026-06-17T14:00:00Z","\u002F2026\u002F06\u002F17\u002Fwindows-11-a-debloat-and-hardening-baseline-for-new-deployments\u002F",[1931],[1994,1995,1945,1944],"windows-11","debloat",[1929],{"doc":1937,"posts":1998},[],1790052513867]