WPNinjas HeaderWPNinjas Header

Cleanup duplicated devices in Intune

In nearly every environment I detect duplicated devices which make most of the reports incorrect and it makes it hard for the support staff to find the correct device of a user. This script basically will remove all devices which have another object with the same serialNumber and are not the one which connected last to the Intune service. But what can lead to duplicated entries? This most often happens when the users reset a device and just re-enroll the device again. One option is to use the Intune Connector for Active Directory Extender which can clean up duplicated devices automatically when the user re-enrolls the Windows devices. But this works only for Hybrid Joined Windows devices, for all others it’s necessary to cleanup them in a scheduled interval.

Before executing the Cmdlet you should install the Intune PowerShell module by executing:

Install-Module Microsoft.Graph.Intune

And connect to your Intune environment:


Download the script from Github

Then on the first run I recommend checking first which devices would be removed by executing it with “-WhatIf”:

.\Invoke-IntuneCleanup -Whatif | Out-GridView

Now we can verify the result in the Intune console. We see that the script was correct, there are two entries for the serial Number and it returned the older device based on the last Sync information.

Next we can start the work and cleanup. There are two options, do it manually or let the Cmdlet just work.

Manual and controlled removal

Execute the following command:

.\Invoke-IntuneCleanup -Whatif | Out-GridView -OutputMode Multiple | foreach-Object { Remove-DeviceManagement_ManagedDevices -managedDnot connectedeviceId $_.id }

Then you will get a grid view where you can select the devices to remove and click on ok.

IMPORTANT: This does not delete the AzureAD Device Object! This is because:

  • In some conditions a device is generating a new object in Azure AD, but because Bitlocker was already enabled the Recovery Key is not written to the actual object.
  • If you are using Autopilot you should also not cleanup AzureAD Objects because they are holding the AzureAD hashes. THANKS Karsten Kleinschmidt for this feedback.

If you are not using Autopilot and would like to remove old AzureAD objects I recommend to check the existence of the Bitlocker recovery key on the new object and if necessary to trigger the backup of the recovery key by deploying a PowerShell script over Intune to your devices with a missing Bitlocker recovery key:

#Narrow scope to applicable recovery protector
$AllProtectors = (Get-BitlockerVolume -MountPoint $env:SystemDrive).KeyProtector
$RecoveryProtector = ($AllProtectors | where-object { $_.KeyProtectorType -eq "RecoveryPassword" })

#Push Recovery Passoword AAD
BackupToAAD-BitLockerKeyProtector $env:systemdrive -KeyProtectorId $RecoveryProtector.KeyProtectorID

If you did that or are you would like to delete the according AzureAD object, then you need to Connect to Azure AD (Connect-AzureAD) and then modify the above Lines to:

$devicesToRemove = .\Invoke-IntuneCleanup -Whatif | Out-GridView -OutputMode Multiple 

foreach($deviceToRemove in $devicesToRemove) { 
    Remove-DeviceManagement_ManagedDevices -managedDnot connectedeviceId $deviceToRemove.id 
    Remove-AzureADDevice -ObjectId $deviceToRemove.azureADDeviceId

Automatic removal

The automatic removal is just simple, just run:


And all is done for you. In most cases I execute this scheduled on Azure automation or another schedule engine.

IMPORTANT: This does not delete the AzureAD Device Object! If you need this, then please use the manual and controlled way a explained above.

I hope this script helps you like me. If you have feedback just leave a comment :).

Follow me


Peter · March 25, 2020 at 10:56

Hi. Thanks for the excellent article and script. In an environment with more than 1000 devices you should use

Get-IntuneManagedDevice | Get-MSGraphAllPages


    Thomas Kurth · March 27, 2020 at 00:01

    Thank you, have just updated the script!

Phil · July 18, 2020 at 01:44

Hi, Does this work for co-managed devices? I ran the script and it reports 4 serialnumbers with duplicated entries, however they do not get removed. I run the script again and same result

    Thomas Kurth · July 20, 2020 at 07:30

    Hello Phil,

    Have you just executed the script or used the manual and controlled way? In the second case do you see the duplicated devices in the Out-GridView?

      Kevin · December 17, 2020 at 17:44

      I am doing co-management and am noticing this behavior. I’ve spot checked a handful of devices that show up on out-gridview and they are still in Intune.

      I ran out-gridview right after running automatic cleanup, and again after 30 minutes, each time the script reports 192 duplicate serial number entries.

        Thomas Kurth · January 1, 2021 at 15:30

        Is your AzureAD and Intune PowerShell Module on an actual version?

Steve · January 26, 2021 at 16:27

Hi Thomas, thanks for the script! When I try to run the managed method, I get the result

“A parameter cannot be found that matches parameter name ‘managedDnot’.”

For each selected object.

    Rob · April 5, 2021 at 21:15

    yeah there is definitely a typo there but if you change it to be

    foreach($deviceToRemove in $devicesToRemove) {
    Remove-DeviceManagement_ManagedDevices -managedDeviceId $deviceToRemove.id
    Remove-AzureADDevice -ObjectId $deviceToRemove.azureADDeviceId

    I am guessing that the author was typing a code comment or this article and somehow likely wristdrag the cursor ended up in the wrong place which he hadn’t noticed

Christian H: · March 9, 2021 at 08:21

Hey Thomas,
nice Script. However, if you have a lot of different devices in your tenant (like self-build pc) you should slightly modify the script.
In line 37 i modified the serialnumber filter to
Where-Object | (-not [String]::IsNullOrWhiteSpace($_.serialNumber)) -and ($_.serialNumber -notin @(“NotApplicable”, “ToBeFilledByO.E.M”, “SystemSerialNumber”, “Defaultstring”))

If I missed a general entry, these should also be added. Otherwise, you could delete a bunch of used devices.

Kind Regards,

    Thomas Kurth · April 25, 2021 at 19:33

    Thanks for this feedback. Definitely you should test the script before executing it.

PeeGee · May 26, 2021 at 10:24

Hi Thomas!
Thanks for your article, but i think you forget some delete from this sentence 🙂
IMPORTANT: This does not the AzureAD Device Object!

    Thomas Kurth · June 13, 2021 at 08:27

    Thanks for the feedback. I changed it.

Sandra · September 21, 2021 at 08:52

Is there a way to tell the script to only remove devices that have been declared non-compliant for more than x days?

    Thomas Kurth · October 26, 2021 at 08:29

    Hello Sandro, currently no, but this can be expanded without an issue. You could update line 42 to something like:

    $devices = Get-IntuneManagedDevice | Get-MSGraphAllPages | Where-Object { $_.complianceState -eq "noncompliant" }

    and then compare the lastSyncDateTime property.
    But this is untested

James · October 11, 2022 at 22:57

Is this still working? the output looks like it succeded but all devices remain in the tenant.

    Thomas Kurth · November 11, 2022 at 12:01

    Yes, this works. I tried it in my tenant.

Kirsten · January 5, 2023 at 09:41

Hello Thomas, thanks for the script Is there a typo in this please?

.\Invoke-IntuneCleanup -Whatif | Out-GridView -OutputMode Multiple | foreach-Object { Remove-DeviceManagement_ManagedDevices -managedDnot connectedeviceId $_.id }

I get an error as ManagedDnot isn’t a correct command? Thanks!

    Thomas Kurth · January 30, 2023 at 13:00

    It depends on the Intune PowerShell Module which you have installed. Check what parameters are available in yours and replace the command.

Dowst.Dev | PowerShell Weekly – September 20, 2019 · September 20, 2019 at 13:54

[…] Cleanup duplicated devices in Intune Cleanup duplicated Windows10 devices in Intune! PowerShell ModernWorkplace WindowsAutopilot s://t.co/e98JdwhYED […]

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.