IntuneDuplicateDeviceCleanup.ps1


<#PSScriptInfo
 
.VERSION 1.0
 
.GUID cdc20c9b-f9f0-47b0-adad-304f06f98246
 
.AUTHOR Vikas Sukhija https://techwizard.cloud/ https://syscloudpro.com/
 
.COMPANYNAME https://techwizard.cloud/ https://syscloudpro.com/
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 http://techwizard.cloud/2020/05/27/intune-duplicate-device-cleanup/
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Intune Duplicate Device Cleanup
 
#>
 
param (
  [string]$smtpserver = $(Read-Host "Enter SMTP Server"),
  [string]$from = $(Read-Host "Enter From Address"),
  [string]$email1 = $(Read-Host "Enter email Address for reports"),
  [string]$erroremail = $(Read-Host "Enter Address for Alerts and Errors"),
  [string]$reportOnly = $(Read-Host "Yes for Just report and No for removing duplicate records"),
  [string]$userId = $(Read-Host "Enter the Admin User id to conenct to Intune"),
  $pwd = $(Read-Host "Enter the passwrod" -AsSecureString),
  $countofchanges = $(Read-Host "Enter Count of changes to process before it breaks")
)

function Write-Log
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [array]$Name,
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [string]$Ext,
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')]
    [string]$folder,
    
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create,
    
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')]
    [String]$Message,
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')]
    [String]$path,
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')]
    [ValidateSet('Information','Warning','Error')]
    [string]$Severity = 'Information',
    
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG
  )
  switch ($PsCmdlet.ParameterSetName) {
    "Create"
    {
      $log = @()
      $date1 = Get-Date -Format d
      $date1 = $date1.ToString().Replace("/", "-")
      $time = Get-Date -Format t
    
      $time = $time.ToString().Replace(":", "-")
      $time = $time.ToString().Replace(" ", "")
    
      foreach ($n in $Name)
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"}
      return $log
    }
    "Message"
    {
      $date = Get-Date
      $concatmessage = "|$date" + "| |" + $Message +"| |" + "$Severity|"
      switch($Severity){
        "Information"{Write-Host -Object $concatmessage -ForegroundColor Green}
        "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow}
        "Error"{Write-Host -Object $concatmessage -ForegroundColor Red}
      }
      
      Add-Content -Path $path -Value $concatmessage
    }
  }
} #Function Write-Log
function Start-ProgressBar
{
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true)]
    $Title,
    [Parameter(Mandatory = $true)]
    [int]$Timer
  )
    
  For ($i = 1; $i -le $Timer; $i++)
  {
    Start-Sleep -Seconds 1;
    Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /100 * 100)
  }
}

#################Check if logs folder is created####
$logpath  = (Get-Location).path + "\logs" 
$testlogpath = Test-Path -Path $logpath
if($testlogpath -eq $false)
{
  Start-ProgressBar -Title "Creating logs folder" -Timer 10
  New-Item -Path (Get-Location).path -Name Logs -Type directory
}
$Reportpath  = (Get-Location).path + "\Report" 
$testlogpath = Test-Path -Path $Reportpath
if($testlogpath -eq $false)
{
  Start-ProgressBar -Title "Creating Report folder" -Timer 10
  New-Item -Path (Get-Location).path -Name Report -Type directory
}

####################Load variables and log####################
$log = Write-Log -Name "Intunedupdevicecleanup-Log" -folder "logs" -Ext "log"
$Report1 = Write-Log -Name "IntunedupdevicesNewOLD-Report" -folder "Report" -Ext "csv"
$Report2 = Write-Log -Name "IntunedupdevicesCleanup-Report" -folder "Report" -Ext "csv"
Write-Log -Message "Start.......Script" -path $log
$collection1 = @()
$collection2 = @()
##################Userid & password#################
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd

################connect to modules###################
try
{
  Import-Module -Name activedirectory
  Connect-AzureAD -Credential $Credential
  Write-Log -Message "AD Module Loaded" -path $log 
  Connect-MSGraph -PSCredential $Credential
  Write-Log -Message "Intune Module Loaded" -path $log
}
catch
{
  $exception = $_.Exception
  Write-Log -Message "Error loading AD/Intune Module Loaded" -path $log -Severity Error 
  Write-Log -Message $exception -path $log -Severity error
  Send-MailMessage -SmtpServer $smtpserver -To $erroremail -From $from -Subject "Error has occured loading AD?intune Module - IntuneDuplicateDeviceCleanup" -Body $($_.Exception.Message)
  Exit
}

#####################process devicess####################
try{
  $getalldevices = Get-IntuneManagedDevice | Get-MSGraphAllPages
  $countdevices = $getalldevices.count
  Write-Log -Message "Count of devices $countdevices" -path $log 
  $Groupdevices = $getalldevices | Where-Object { -not [String]::IsNullOrWhiteSpace($_.serialNumber) } | Group-Object -Property serialNumber ###get where serail number is not blank
  $findduplicatedDevices = $Groupdevices | Where-Object {$_.Count -gt 1 }
  $countdupdevices = $findduplicatedDevices.count
  Write-Log -Message "Count of entries that are duplicate $countdupdevices" -path $log
}
catch{
  $exception = $_.Exception
  Write-Log -Message "Error occured fetching duplicate entries" -path $log -Severity Error 
  Write-Log -Message $exception -path $log -Severity error
  Send-MailMessage -SmtpServer $smtpserver -To $erroremail -From $from -Subject "Error occured fetching duplicate entries - IntuneDuplicateDeviceCleanup" -Body $($_.Exception.Message)
  Exit

}
 Write-Log -Message "Count of entries that are duplicate $countdupdevices" -path $log
 
############################Find the devices for removal#######################
  foreach($entry in $findduplicatedDevices){
    $mcoll = "" | Select deviceName,emailAddress,serialNumber,operatingSystem,enrolledDateTime,lastSyncDateTime,ID,Status
    $newDevice = $entry.Group | Sort-Object -Property lastSyncDateTime -Descending | Select-Object -First 1
    $mcoll.deviceName = $newDevice.deviceName
    $mcoll.emailAddress = $newDevice.emailAddress
    $mcoll.serialNumber = $newDevice.serialNumber
    $mcoll.operatingSystem = $newDevice.operatingSystem
    $mcoll.enrolledDateTime = $newDevice.enrolledDateTime
    $mcoll.lastSyncDateTime = $newDevice.lastSyncDateTime
    $mcoll.ID= $newDevice.ID
    $mcoll.Status = "NewDevice"
    $collection1+=$mcoll
    $srlnum = $newDevice.serialNumber
    $emladd = $newDevice.emailAddress
    Write-Log -Message "NewDevice...........$srlnum - $emladd" -path $log 
    $mcoll=$null
    foreach($oldDevice in ($entry.Group | Sort-Object -Property lastSyncDateTime -Descending | Select-Object -Skip 1)){
      $mcoll = "" | Select deviceName,emailAddress,serialNumber,operatingSystem,enrolledDateTime,lastSyncDateTime,ID,Status
      $mcoll.deviceName = $oldDevice.deviceName
      $mcoll.emailAddress = $oldDevice.emailAddress
      $mcoll.serialNumber = $oldDevice.serialNumber
      $mcoll.operatingSystem = $oldDevice.operatingSystem
      $mcoll.enrolledDateTime = $oldDevice.enrolledDateTime
      $mcoll.lastSyncDateTime = $oldDevice.lastSyncDateTime
      $mcoll.ID= $oldDevice.ID
      $mcoll.Status = "OldDevice"
      $collection1+=$mcoll
      $srlnum = $oldDevice.serialNumber
      $emladd = $oldDevice.emailAddress
      Write-Log -Message "NewDevice...........$srlnum - $emladd" -path $log 
      $mcoll=$null
    }
  }
  $collection1 | Export-Csv $Report1 -NoTypeInformation
  $olddeivescollection = $collection1 | where{$_.status  -eq "OldDevice"}
  $olddeivesremovecount = $olddeivescollection.count
   Write-Log -Message "Count of devices $olddeivesremovecount" -path $log 
##################################################################################
$mcoll=$null
if(($olddeivesremovecount-gt 0) -and ($olddeivesremovecount -lt $countofchanges)) {
  $olddeivescollection | ForEach-Object{
    $error.clear()
    $mcoll = "" | Select deviceName,emailAddress,serialNumber,operatingSystem,enrolledDateTime,lastSyncDateTime,ID,Status
      $mcoll.deviceName = $_.deviceName
      $mcoll.emailAddress = $_.emailAddress
      $mcoll.serialNumber = $_.serialNumber
      $mcoll.operatingSystem = $_.operatingSystem
      $mcoll.enrolledDateTime = $_.enrolledDateTime
      $mcoll.lastSyncDateTime = $_.lastSyncDateTime
      $mcoll.ID= $_.ID
      $srlnum = $_.serialNumber
      $emladd = $_.emailAddress
      $mgid = $_.ID
      try{
      if($reportonly -eq "No"){
        Remove-IntunemanagedDevice -manageddeviceID $_.ID
        if($error){
          $mcoll.Status= "Error"
          Write-Log -Message "Error occured deleting entry $srlnum - $emladd - $mgid" -path $log -Severity Error 
        }else{
          $mcoll.Status= "Success"
          Write-Log -Message "Success deleting entry $srlnum - $emladd - $mgid" -path $log 
        }
        }
      if($reportonly -eq "Yes"){
         $mcoll.Status= "ReportOnlyMode"
         Write-Log -Message "Report onlymode - deleting entry $srlnum - $emladd - $mgid" -path $log
       } 
      }
      catch{
      
        $mcoll.ID= "Exception"
        $exception = $_.Exception
        Write-Log -Message "Error occured deleting entry $srlnum - $emladd - $mgid" -path $log -Severity Error 
        Write-Log -Message $exception -path $log -Severity error
      }
      $collection2 +=$mcoll
  }

  $collection2 | Export-Csv $Report2 -NoTypeInformation
}

elseif($olddeivesremovecount -gt $countofchanges)
{
  Write-Log -Message "Count is $olddeivesremovecount greater than $countofchanges" -path $log -Severity error
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error Count is $olddeivesremovecount greater than $countofchanges - IntuneDuplicateDeviceCleanup" -Body "Error Count is $olddeivesremovecount greater than $countofchanges - IntuneDuplicateDeviceCleanup"
  exit;

}

Write-Log -Message "Finish processing........ Duplicate entries" -path $log
Send-MailMessage -SmtpServer $smtpserver -From $from -To $email1 -bcc $erroremail -Subject "Reports - IntuneDuplicateDeviceCleanup" -Body "Reports - IntuneDuplicateDeviceCleanup" -Attachments $report1,$report2
##############################################################################
$path1 = $logpath
$path2 = $Reportpath

$limit = (Get-Date).AddDays(-60) #for report recycling
Get-ChildItem -Path $path1 |
Where-Object -FilterScript {$_.CreationTime -lt $limit} |
Remove-Item -Recurse -Force

Get-ChildItem -Path $path2 |
Where-Object -FilterScript {$_.CreationTime -lt $limit} |
Remove-Item -Recurse -Force

Write-Log -Message "Script Finished" -path $log
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "IntuneDuplicateDeviceCleanup - log" -Body "IntuneDuplicateDeviceCleanup - log" -Attachments $log
################################################################################