Skip to content

Instantly share code, notes, and snippets.

@SMSAgentSoftware
Last active January 18, 2024 18:35
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save SMSAgentSoftware/27ff318f3973b97ca6b5cb99e8c93293 to your computer and use it in GitHub Desktop.
Save SMSAgentSoftware/27ff318f3973b97ca6b5cb99e8c93293 to your computer and use it in GitHub Desktop.
Deletes device records in AD / AAD / Intune / Autopilot / ConfigMgr. Useful for Autopilot test deployments.
[CmdletBinding(DefaultParameterSetName='All')]
Param
(
[Parameter(ParameterSetName='All',Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
[Parameter(ParameterSetName='Individual',Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
[string[]]$ComputerName,
[Parameter(ParameterSetName='All')]
[switch]$All = $True,
[Parameter(ParameterSetName='Individual')]
[switch]$AD,
[Parameter(ParameterSetName='Individual')]
[switch]$AAD,
[Parameter(ParameterSetName='Individual')]
[switch]$Intune,
[Parameter(ParameterSetName='Individual')]
[switch]$Autopilot,
[Parameter(ParameterSetName='Individual')]
[switch]$ConfigMgr
)
<#
******************
** REQUIREMENTS **
******************
For AD, the host workstation must be joined to the domain and have line-of-sight to a domain controller.
For ConfigMgr, the host workstation must have the ConfigMgr PowerShell module installed.
For Azure AD, Intune and Autopilot, the Microsoft Graph PowerShell enterprise application with app Id 14d82eec-204b-4c2f-b7e8-296a70dab67e must have the following
permissions granted with admin consent:
- Directory.AccessAsUser.All (for Azure AD)
- DeviceManagementManagedDevices.ReadWrite.All (for Intune)
- DeviceManagementServiceConfig.ReadWrite.All (for Autopilot)
For all scenarios, the user account must have the appropriate permissions to read and delete the device records.
The required MS Graph modules will be installed for the user if not already present.
!! Updated 2023-07-14 to use the v2 of Microsoft Graph PowerShell SDK !!
#>
Begin
{
Set-Location $env:SystemDrive
# Load required modules
#region Modules
If ($PSBoundParameters.ContainsKey("AAD") -or $PSBoundParameters.ContainsKey("Intune") -or $PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All"))
{
Write-Host "Importing modules"
# Get NuGet
$provider = Get-PackageProvider NuGet -ErrorAction Ignore
if (-not $provider)
{
Write-Host "Installing provider NuGet..." -NoNewline
try
{
Find-PackageProvider -Name NuGet -ForceBootstrap -IncludeDependencies -Force -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Failed" -ForegroundColor Red
throw $_.Exception.Message
return
}
}
$module = Import-Module Microsoft.Graph.Identity.DirectoryManagement -PassThru -ErrorAction Ignore
if (-not $module)
{
Write-Host "Installing module Microsoft.Graph.Identity.DirectoryManagement..." -NoNewline
try
{
Install-Module Microsoft.Graph.Identity.DirectoryManagement -Scope CurrentUser -Force -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Failed" -ForegroundColor Red
throw $_.Exception.Message
return
}
}
$module = Import-Module Microsoft.Graph.DeviceManagement -PassThru -ErrorAction Ignore
if (-not $module)
{
Write-Host "Installing module Microsoft.Graph.DeviceManagement..." -NoNewline
try
{
Install-Module Microsoft.Graph.DeviceManagement -Scope CurrentUser -Force -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Failed" -ForegroundColor Red
throw $_.Exception.Message
return
}
}
$module = Import-Module Microsoft.Graph.DeviceManagement.Enrollment -PassThru -ErrorAction Ignore
if (-not $module)
{
Write-Host "Installing module Microsoft.Graph.DeviceManagement.Enrollment..." -NoNewline
try
{
Install-Module Microsoft.Graph.DeviceManagement.Enrollment -Scope CurrentUser -Force -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Failed" -ForegroundColor Red
throw $_.Exception.Message
return
}
}
}
If ($PSBoundParameters.ContainsKey("ConfigMgr") -or $PSBoundParameters.ContainsKey("All"))
{
$SMSEnvVar = [System.Environment]::GetEnvironmentVariable('SMS_ADMIN_UI_PATH')
If ($SMSEnvVar)
{
$ModulePath = $SMSEnvVar.Replace('i386','ConfigurationManager.psd1')
if ([System.IO.File]::Exists($ModulePath))
{
try
{
Import-Module $ModulePath -ErrorAction Stop
}
catch
{
throw "Failed to import ConfigMgr module: $($_.Exception.Message)"
}
}
else
{
throw "ConfigMgr module not found"
}
}
else
{
throw "SMS_ADMIN_UI_PATH environment variable not found"
}
}
#endregion
#region Auth
If ($PSBoundParameters.ContainsKey("AAD") -or $PSBoundParameters.ContainsKey("Intune") -or $PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All"))
{
Write-Host "Authenticating..." -NoNewline
try
{
$null = Connect-MgGraph -Scopes "Directory.AccessAsUser.All","DeviceManagementManagedDevices.ReadWrite.All","DeviceManagementServiceConfig.ReadWrite.All" -ErrorAction Stop
#$null = Connect-MgGraph -Scopes "Directory.AccessAsUser.All","DeviceManagementServiceConfig.ReadWrite.All" -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Failed" -ForegroundColor Red
throw $_.Exception.Message
}
}
#endregion
}
Process
{
foreach ($Computer in $ComputerName)
{
Write-Host "==============="
Write-host "$($Computer.ToUpper())"
Write-Host "==============="
#region AD
If ($PSBoundParameters.ContainsKey("AD") -or $PSBoundParameters.ContainsKey("All"))
{
Try
{
Write-host "Locating device in " -NoNewline
Write-host "Active Directory" -ForegroundColor Blue -NoNewline
Write-Host "..." -NoNewline
$Searcher = [ADSISearcher]::new()
$Searcher.Filter = "(sAMAccountName=$Computer`$)"
[void]$Searcher.PropertiesToLoad.Add("distinguishedName")
$ComputerAccount = $Searcher.FindOne()
If ($ComputerAccount)
{
Write-host "Success" -ForegroundColor Green
Write-Host "Removing device from" -NoNewline
Write-Host "Active Directory" -NoNewline -ForegroundColor Blue
Write-Host "..." -NoNewline
$DirectoryEntry = $ComputerAccount.GetDirectoryEntry()
$Result = $DirectoryEntry.DeleteTree()
Write-Host "Success" -ForegroundColor Green
}
Else
{
Write-host "Fail" -ForegroundColor Red
Write-Warning "Device not found in Active Directory"
}
}
Catch
{
Write-host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
}
}
#endregion
#region AzureAD
If ($PSBoundParameters.ContainsKey("AAD") -or $PSBoundParameters.ContainsKey("All"))
{
Write-Host "Locating device in" -NoNewline
Write-Host " Azure AD" -NoNewline -ForegroundColor Yellow
Write-Host "..." -NoNewline
try
{
$AADDevice = Get-MgDevice -Search "displayName:$Computer" -CountVariable CountVar -ConsistencyLevel eventual -ErrorAction Stop
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
$LocateInAADFailure = $true
}
If ($LocateInAADFailure -ne $true)
{
If ($AADDevice.Count -eq 1)
{
Write-Host "Success" -ForegroundColor Green
Write-Host " DisplayName: $($AADDevice.DisplayName)"
Write-Host " ObjectId: $($AADDevice.Id)"
Write-Host " DeviceId: $($AADDevice.DeviceId)"
Write-Host "Removing device from" -NoNewline
Write-Host " Azure AD" -NoNewline -ForegroundColor Yellow
Write-Host "..." -NoNewline
try
{
$Result = Remove-MgDevice -DeviceId $AADDevice.Id -PassThru -ErrorAction Stop
If ($Result -eq $true)
{
Write-Host "Success" -ForegroundColor Green
}
else
{
Write-Host "Fail" -ForegroundColor Red
}
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
}
}
ElseIf ($AADDevice.Count -gt 1)
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Multiple devices found in Azure AD. The device display name must be unique."
}
else
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Device not found in Azure AD"
}
}
}
#endregion
#region Intune
If ($PSBoundParameters.ContainsKey("Intune") -or $PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All"))
{
Write-Host "Locating device in" -NoNewline
Write-Host " Intune" -NoNewline -ForegroundColor Cyan
Write-Host "..." -NoNewline
try
{
$IntuneDevice = Get-MgDeviceManagementManagedDevice -Filter "deviceName eq '$Computer'" -ErrorAction Stop
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
$LocateInIntuneFailure = $true
}
If ($LocateInIntuneFailure -ne $true)
{
If ($IntuneDevice.Count -eq 1)
{
Write-Host "Success" -ForegroundColor Green
Write-Host " DeviceName: $($IntuneDevice.DeviceName)"
Write-Host " ObjectId: $($IntuneDevice.Id)"
Write-Host " AzureAdDeviceId: $($IntuneDevice.AzureAdDeviceId)"
Write-Host "Removing device from" -NoNewline
Write-Host " Intune" -NoNewline -ForegroundColor Cyan
Write-Host "..." -NoNewline
try
{
$Result = Remove-MgDeviceManagementManagedDevice -ManagedDeviceId $IntuneDevice.Id -PassThru -ErrorAction Stop
If ($Result -eq $true)
{
Write-Host "Success" -ForegroundColor Green
}
else
{
Write-Host "Fail" -ForegroundColor Red
}
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
}
}
ElseIf ($IntuneDevice.Count -gt 1)
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Multiple devices found in Intune. The device display name must be unique."
}
else
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Device not found in Intune"
}
}
}
#endregion
#region Autopilot
If (($PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All")) -and $IntuneDevice.Count -eq 1)
{
Write-Host "Locating device in" -NoNewline
Write-Host " Windows Autopilot" -NoNewline -ForegroundColor Cyan
Write-Host "..." -NoNewline
try
{
$AutopilotDevice = Get-MgDeviceManagementWindowsAutopilotDeviceIdentity -Filter "contains(serialNumber,'$($IntuneDevice.SerialNumber)')" -ErrorAction Stop
#$Response = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/deviceManagement/windowsAutopilotDeviceIdentities?`$filter=contains(serialNumber,'$SerialNumber')" -ErrorAction Stop
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
$LocateInAutopilotFailure = $true
}
If ($LocateInAutopilotFailure -ne $true)
{
If ($AutopilotDevice.Count -eq 1)
{
Write-Host "Success" -ForegroundColor Green
Write-Host " SerialNumber: $($AutopilotDevice.SerialNumber)"
Write-Host " Id: $($AutopilotDevice.Id)"
Write-Host " ManagedDeviceId: $($AutopilotDevice.ManagedDeviceId)"
Write-Host " Model: $($AutopilotDevice.Model)"
Write-Host " GroupTag: $($AutopilotDevice.GroupTag)"
Write-Host "Removing device from" -NoNewline
Write-Host " Windows Autopilot" -NoNewline -ForegroundColor Cyan
Write-Host "..." -NoNewline
try
{
$Result = Remove-MgDeviceManagementWindowsAutopilotDeviceIdentity -WindowsAutopilotDeviceIdentityId $AutopilotDevice.Id -PassThru -ErrorAction Stop
If ($Result -eq $true)
{
Write-Host "Success" -ForegroundColor Green
}
else
{
Write-Host "Fail" -ForegroundColor Red
}
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
}
}
ElseIf ($AutopilotDevice.Count -gt 1)
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Multiple devices found in Windows Autopilot. The serial number must be unique."
Continue
}
else
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Device not found in Windows Autopilot"
}
}
}
#endregion
#region ConfigMgr
If ($PSBoundParameters.ContainsKey("ConfigMgr") -or $PSBoundParameters.ContainsKey("All"))
{
Write-host "Locating device in " -NoNewline
Write-host "ConfigMgr " -ForegroundColor Magenta -NoNewline
Write-host "..." -NoNewline
Try
{
$SiteCode = (Get-PSDrive -PSProvider CMSITE -ErrorAction Stop).Name
Set-Location ("$SiteCode" + ":") -ErrorAction Stop
[array]$ConfigMgrDevices = Get-CMDevice -Name $Computer -Fast -ErrorAction Stop
}
Catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
$LocateInConfigMgrFailure = $true
}
If ($LocateInConfigMgrFailure -ne $true)
{
If ($ConfigMgrDevices.count -eq 1)
{
$ConfigMgrDevice = $ConfigMgrDevices[0]
Write-Host "Success" -ForegroundColor Green
Write-Host " ResourceID: $($ConfigMgrDevice.ResourceID)"
Write-Host " SMSID: $($ConfigMgrDevice.SMSID)"
Write-Host " UserDomainName: $($ConfigMgrDevice.UserDomainName)"
Write-Host "Removing device from" -NoNewline
Write-Host " ConfigMgr" -NoNewline -ForegroundColor Magenta
Write-Host "..." -NoNewline
try
{
Remove-CMDevice -InputObject $ConfigMgrDevice -Force -ErrorAction Stop
Write-Host "Success" -ForegroundColor Green
}
catch
{
Write-Host "Fail" -ForegroundColor Red
Write-Error "$($_.Exception.Message)"
}
}
ElseIf ($ConfigMgrDevices.Count -gt 1)
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Multiple devices found in ConfigMgr The device name must be unique."
Continue
}
else
{
Write-Host "Fail" -ForegroundColor Red
Write-Warning "Device not found in ConfigMgr"
}
}
}
#endregion
}
}
End
{
Set-Location $env:SystemDrive
If ($PSBoundParameters.ContainsKey("AAD") -or $PSBoundParameters.ContainsKey("Intune") -or $PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All"))
{
$null = Disconnect-MgGraph -ErrorAction SilentlyContinue
}
}
@RaghuKeenLearner
Copy link

RaghuKeenLearner commented Jun 17, 2022 via email

@rmuhammad4
Copy link

This worked for me. But the device was still in MSfB, I had to delete it from there then re-import csv.

@jcgm1990
Copy link

jcgm1990 commented Oct 6, 2022

When I run this script, all it does is asks for the computer to delete, it doesn't prompt to connect to AAD or anything else

@automationfella
Copy link

Same here.

@SMSAgentSoftware
Copy link
Author

Same here.

Make sure you wrap the script in a function and make sure you have the required modules installed.

@RaghuKeenLearner
Copy link

@SMSAgentSoftware Hi Trevor, I beleive with new updates from MS, this script is no longer working.
First I kept on getting error "WARNING: The version '6.1907.1.0' of module 'Microsoft.Graph.Intune' is currently in use. Retry the operation after closing the applications."
followed by " WARNING: The version '2.0.2.180' of module 'AzureAD' is currently in use. Retry the operation after closing the applications.
VERBOSE: Module 'AzureAD' is in currently in use or you don't have the required permissions."
Authenticating with MS Graph and Azure AD...Error!
One or more errors occurred.

I am logged in as GlobalAdmin and I can authenitcate with Azure if I use Connect-AzureAD

any tips to fix this error?

@SMSAgentSoftware
Copy link
Author

@SMSAgentSoftware Hi Trevor, I beleive with new updates from MS, this script is no longer working. First I kept on getting error "WARNING: The version '6.1907.1.0' of module 'Microsoft.Graph.Intune' is currently in use. Retry the operation after closing the applications." followed by " WARNING: The version '2.0.2.180' of module 'AzureAD' is currently in use. Retry the operation after closing the applications. VERBOSE: Module 'AzureAD' is in currently in use or you don't have the required permissions." Authenticating with MS Graph and Azure AD...Error! One or more errors occurred.

I am logged in as GlobalAdmin and I can authenitcate with Azure if I use Connect-AzureAD

any tips to fix this error?

Thanks for the heads-up - I’ll check it out after my vacation.

@SMSAgentSoftware
Copy link
Author

I tested the script and it still works (at least for me). You may have multiple module versions installed which could cause this error.

@pctech2006
Copy link

I cannot get this script to work at all. It gets past "Importing Modules....Success". But then it does this "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." It never does prompt for user or password. I have verified that the correct modules are installed. I can authenticate with Connect-MSGraph and Connect-AzureAD manually via powershell. What am I missing?

@RaghuKeenLearner
Copy link

I cannot get this script to work at all. It gets past "Importing Modules....Success". But then it does this "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." It never does prompt for user or password. I have verified that the correct modules are installed. I can authenticate with Connect-MSGraph and Connect-AzureAD manually via powershell. What am I missing?

this is what I did to fix this issue,
Rebooted the machine.
Deleted the content of "C:\Program Files\WindowsPowerShell\Modules"
Re-Ran the script and it downloaded everything and worked fine for most part.

@SMSAgentSoftware Trevor, now it is working, but I don't see AutoPilot anymore and it doesn't remove the device/serial from the AP anymore.
image

@SMSAgentSoftware
Copy link
Author

SMSAgentSoftware commented Jun 29, 2023

I cannot get this script to work at all. It gets past "Importing Modules....Success". But then it does this "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." It never does prompt for user or password. I have verified that the correct modules are installed. I can authenticate with Connect-MSGraph and Connect-AzureAD manually via powershell. What am I missing?

this is what I did to fix this issue, Rebooted the machine. Deleted the content of "C:\Program Files\WindowsPowerShell\Modules" Re-Ran the script and it downloaded everything and worked fine for most part.

@SMSAgentSoftware Trevor, now it is working, but I don't see AutoPilot anymore and it doesn't remove the device/serial from the AP anymore. image

If the device isn't found in Intune, it won't look for an Autopilot record. If it's in Intune and has an AP record, it does remove it.

image

@pctech2006
Copy link

Is there some type of permissions that need to be setup in Azure for the Microsoft Graph? I now have the script prompting for username and password (logging in as a global admin). After I login it instantly comes up with this error "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." Also, I cannot get this script to run with the "-All" argument.

Capture

@SMSAgentSoftware
Copy link
Author

Is there some type of permissions that need to be setup in Azure for the Microsoft Graph? I now have the script prompting for username and password (logging in as a global admin). After I login it instantly comes up with this error "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." Also, I cannot get this script to run with the "-All" argument.

Capture

Are you running in PS 5.1?

@pctech2006
Copy link

PSVersion 5.1.19041.3031

@SMSAgentSoftware
Copy link
Author

I'm gonna update the module dependencies in the script since they are old now...hang slack for a few hours :)

@RaghuKeenLearner
Copy link

Is there some type of permissions that need to be setup in Azure for the Microsoft Graph? I now have the script prompting for username and password (logging in as a global admin). After I login it instantly comes up with this error "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." Also, I cannot get this script to run with the "-All" argument.

Capture

I wouldn't recommend deleting device from AP before AAD.

@RaghuKeenLearner
Copy link

I cannot get this script to work at all. It gets past "Importing Modules....Success". But then it does this "Authenticating with MS Graph and Azure AD...Error! One or more errors occurred." It never does prompt for user or password. I have verified that the correct modules are installed. I can authenticate with Connect-MSGraph and Connect-AzureAD manually via powershell. What am I missing?

this is what I did to fix this issue, Rebooted the machine. Deleted the content of "C:\Program Files\WindowsPowerShell\Modules" Re-Ran the script and it downloaded everything and worked fine for most part.
@SMSAgentSoftware Trevor, now it is working, but I don't see AutoPilot anymore and it doesn't remove the device/serial from the AP anymore. image

If the device isn't found in Intune, it won't look for an Autopilot record. If it's in Intune and has an AP record, it does remove it.

image

Thanks, Trevor. I will add Remove-AutoPilotDevice script in your script. You are doing an awesome job sir.

@pctech2006
Copy link

@RaghuKeenLearner But Azure AD will not allow you to remove a device unless the Autopilot device has been removed first. We currently manually have to remove from Intune, then Autopilot, then AAD in that order.

@RaghuKeenLearner
Copy link

@RaghuKeenLearner But Azure AD will not allow you to remove a device unless the Autopilot device has been removed first. We currently manually have to remove from Intune, then Autopilot, then AAD in that order.

Well I have been following this recommendation in principal from MS -> For Azure AD join devices, no additional steps are necessary to remove the device from Intune and Autopilot. Unneeded steps include manually deleting the device from Azure AD. Manually deleting the device from Azure AD may cause unexpected problems, issues, and behavior. If needed, the device will be automatically removed from Azure AD after these steps are followed.

Source -> https://learn.microsoft.com/en-us/mem/autopilot/registration-overview

@pctech2006
Copy link

Just checking to see if there was any update on this? Hoping to get this working soon. I have tried to run this on a freshly imaged Windows 10 device again with no luck. Still keep getting the same error. No pressure.

Thanks

@SMSAgentSoftware
Copy link
Author

Sorry for delay...I was waiting for permissions to be granted on the enterprise app to test the updates in a production environment. I have re-written the script to use the Microsoft Graph PowerShell SDK, so there are new module and permissions requirements...these are documented in the script. Let me know if any issues.

@pctech2006
Copy link

@SMSAgentSoftware Thanks. I was able to test this and it is now working great. This really save alot of headaches when you have hundreds of devices to remove. However, there is one thing... Is there a way to get this script to reuse the provided credentials more than once instead of having to authenticate for each individual device?

@SMSAgentSoftware
Copy link
Author

@SMSAgentSoftware Thanks. I was able to test this and it is now working great. This really save alot of headaches when you have hundreds of devices to remove. However, there is one thing... Is there a way to get this script to reuse the provided credentials more than once instead of having to authenticate for each individual device?

Great, thanks for the feedback. The credential prompting issue - have you tried clearing the cache as described here: https://learn.microsoft.com/en-us/answers/questions/1245345/how-can-i-prevent-getting-prompted-multiple-times

@pctech2006
Copy link

@SMSAgentSoftware Thanks. I was able to test this and it is now working great. This really save alot of headaches when you have hundreds of devices to remove. However, there is one thing... Is there a way to get this script to reuse the provided credentials more than once instead of having to authenticate for each individual device?

Great, thanks for the feedback. The credential prompting issue - have you tried clearing the cache as described here: https://learn.microsoft.com/en-us/answers/questions/1245345/how-can-i-prevent-getting-prompted-multiple-times

@SMSAgentSoftware I am running the script below and it works fine. However, when it gets to each device in the list, I have to authenticate each time. Even logged into Windows as the same user. Any suggestions?

$computer_list = Import-Csv "c:\Scripts\ComputerName.csv"
foreach ($computer in $computer_list)
{
C:\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune
}

@pctech2006
Copy link

@SMSAgentSoftware Thanks. I was able to test this and it is now working great. This really save alot of headaches when you have hundreds of devices to remove. However, there is one thing... Is there a way to get this script to reuse the provided credentials more than once instead of having to authenticate for each individual device?

Great, thanks for the feedback. The credential prompting issue - have you tried clearing the cache as described here: https://learn.microsoft.com/en-us/answers/questions/1245345/how-can-i-prevent-getting-prompted-multiple-times

@SMSAgentSoftware I am running the script below and it works fine. However, when it gets to each device in the list, I have to authenticate each time. Even logged into Windows as the same user. Any suggestions?

$computer_list = Import-Csv "c:\Scripts\ComputerName.csv" foreach ($computer in $computer_list) { C:\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune }

@SMSAgentSoftware I was actually able to accomplish this by editing lines 150 and 151 to include -ClientId, -TenantId, and -CertificateThumbprint. Also had to add Appication permissions to the API and add the certificate to the API. When I run the computer list script it then calls the Delete-AutopilotedDeviceRecords.ps1 and authenticates automatically and removes all devices in the list. Thanks for your help.

@SMSAgentSoftware
Copy link
Author

Nice one :) The only thing with app auth is that you can't track the changes to a user as it will appear as the app.
You could still handle multiple devices by changing the $ComputerName parameter to a string array, like [string[]]$ComputerName, then use begin..process..end blocks. The code up to and including the auth section would be in the begin block, the rest in the process block and the last few lines in the end block. The do a foreach on the $ComputerName in the process block. That way you can pass multiple computernames in the $ComputerName parameter and only auth one time.

@pctech2006
Copy link

@SMSAgentSoftware Is there a way to setup the script to delete devices from Autopilot even if they are not in AAD or Intune devices?

@SMSAgentSoftware
Copy link
Author

@SMSAgentSoftware Is there a way to setup the script to delete devices from Autopilot even if they are not in AAD or Intune devices?

It's possible but it doesn't fit the logic of the script which is to locate devices by their computer name. To locate a device in Autopilot I use the serial number as the UID, and we have to first get that from the Intune object.

@M1k3l0ny
Copy link

M1k3l0ny commented Aug 3, 2023

Hey,

First of all, many thanks for the script! Really useful!!!

Question: If I have a CSV file with a list of computers to be deleted instead deleting one by one, what should add to the script and where exactly within the script?

I'm newbie with scripts.

Many thanks in advance!

Best regards

@RaghuKeenLearner
Copy link

Hey,

First of all, many thanks for the script! Really useful!!!

Question: If I have a CSV file with a list of computers to be deleted instead deleting one by one, what should add to the script and where exactly within the script?

I'm newbie with scripts.

Many thanks in advance!

Best regards

Hey it is answered 2 replies above. by @pctech2006 "

$computer_list = Import-Csv "c:\Scripts\ComputerName.csv"
foreach ($computer in $computer_list)
{
C:\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune
}

I was actually able to accomplish this by editing lines 150 and 151 to include -ClientId, -TenantId, and -CertificateThumbprint. Also had to add Appication permissions to the API and add the certificate to the API. When I run the computer list script it then calls the Delete-AutopilotedDeviceRecords.ps1 and authenticates automatically and removes all devices in the list. Thanks for your help."

Cheers

@M1k3l0ny
Copy link

M1k3l0ny commented Aug 3, 2023

Hey,
First of all, many thanks for the script! Really useful!!!
Question: If I have a CSV file with a list of computers to be deleted instead deleting one by one, what should add to the script and where exactly within the script?
I'm newbie with scripts.
Many thanks in advance!
Best regards

Hey it is answered 2 replies above. by @pctech2006 "

$computer_list = Import-Csv "c:\Scripts\ComputerName.csv" foreach ($computer in $computer_list) { C:\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune }

I was actually able to accomplish this by editing lines 150 and 151 to include -ClientId, -TenantId, and -CertificateThumbprint. Also had to add Appication permissions to the API and add the certificate to the API. When I run the computer list script it then calls the Delete-AutopilotedDeviceRecords.ps1 and authenticates automatically and removes all devices in the list. Thanks for your help."

Cheers

Hey,

I saw that answer, but I don't know how to make it...

Should I paste that lines between lines 150 & 151 of the script? Also I don't understand the last paragraph...

Sorry, but I'm almost dumb with scripts. A pasted script would be helpful if possible...

Thanks,

Best regards

@pctech2006
Copy link

@SMSAgentSoftware How can I edit this script to where even if there are multiple devices listed in Azure AD with the same names, that it deletes them all?

@RaghuKeenLearner
Copy link

@SMSAgentSoftware How can I edit this script to where even if there are multiple devices listed in Azure AD with the same names, that it deletes them all?

It doesn't do that for you? Works for me and I am using stock script.

@pctech2006
Copy link

No. I there is only one instance of the device it will delete it. However, If it detects the same computer name multiple times in azure ad it will not delete it. It will just delete it from Intune and Autopilot. It gives an error saying cannot delete device if there are multiple instance with same name or something like that.

@RaghuKeenLearner
Copy link

No. I there is only one instance of the device it will delete it. However, If it detects the same computer name multiple times in azure ad it will not delete it. It will just delete it from Intune and Autopilot. It gives an error saying cannot delete device if there are multiple instance with same name or something like that.

Shoot... well sorry to hear that but for me it deletes all. It shows me all different device IDs in AAD and deletes them too.

@pctech2006
Copy link

I can't figure out why it's not deleting the devices in Azure AD if there is multiple of the same computer name. Lines 250-254 of the script is the error it is throwing. If I can figure out where in the script it is looking to see how many devices are in Azure AD with same name, I may be able to get it working. But I'm not sure.

       ElseIf ($AADDevice.Count -gt 1)
    {
        Write-Host "Fail" -ForegroundColor Red
        Write-Warning "Multiple devices found in Azure AD. The device display name must be unique." 
    }

@SMSAgentSoftware
Copy link
Author

I can't figure out why it's not deleting the devices in Azure AD if there is multiple of the same computer name. Lines 250-254 of the script is the error it is throwing. If I can figure out where in the script it is looking to see how many devices are in Azure AD with same name, I may be able to get it working. But I'm not sure.

       ElseIf ($AADDevice.Count -gt 1)
    {
        Write-Host "Fail" -ForegroundColor Red
        Write-Warning "Multiple devices found in Azure AD. The device display name must be unique." 
    }

Line 210 gets the device from AzureAD, or should I say Entra now?! Anyway, since the computer name is not a unique identifier if more than one device is returned it won’t process any of them since there is no way to know which device record you intended to delete without a UID. If you change the logic to allow that you risk unwanted deletions. Of course in an ideal world there would be no duplicate device names - I could wish that were a UID!

@kdragon15047
Copy link

kdragon15047 commented Sep 14, 2023

Hey,
First of all, many thanks for the script! Really useful!!!
Question: If I have a CSV file with a list of computers to be deleted instead deleting one by one, what should add to the script and where exactly within the script?
I'm newbie with scripts.
Many thanks in advance!
Best regards

Hey it is answered 2 replies above. by @pctech2006 "
$computer_list = Import-Csv "c:\Scripts\ComputerName.csv" foreach ($computer in Unable to render expression.

    $computer_list) { C:\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune }

I was actually able to accomplish this by editing lines 150 and 151 to include -ClientId, -TenantId, and -CertificateThumbprint. Also had to add Appication permissions to the API and add the certificate to the API. When I run the computer list script it then calls the Delete-AutopilotedDeviceRecords.ps1 and authenticates automatically and removes all devices in the list. Thanks for your help."
Cheers

Hey,

I saw that answer, but I don't know how to make it...

Should I paste that lines between lines 150 & 151 of the script? Also I don't understand the last paragraph...

Sorry, but I'm almost dumb with scripts. A pasted script would be helpful if possible...

Thanks,

Best regards

I was wondering if you got this figured out, I need to remove almost 1.5k devices and gets a little annoying

***I edited out the last part and it will run continuously without prompting LIne 451-456

#Set-Location $env:SystemDrive

#If ($PSBoundParameters.ContainsKey("AAD") -or $PSBoundParameters.ContainsKey("Intune") -or $PSBoundParameters.ContainsKey("Autopilot") -or $PSBoundParameters.ContainsKey("All"))
#{

$null = Disconnect-MgGraph -ErrorAction SilentlyContinue

#}

@pctech2006
Copy link

@kdragon15047 You have to create another ps1 script to import your csv and call the Delete-AutopilotedDeviceRecords.ps1 script.

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

$computer_list = Import-Csv "PATH TO CSV FILE"
foreach ($computer in $computer_list)
{
\PATH TO\Delete-AutopilotedDeviceRecords.ps1 -ComputerName $($computer.ComputerName) -Autopilot -AAD -Intune
}

@pctech2006
Copy link

@kdragon15047 Paste these two lines to replace lines150 and 151 of the script. You will have to have Microsoft Graph setup in Azure and you will have to generate a certificate thumbprint in Azure. Replace the X's in the following lines with whatever your Client ID, Tenant ID, and Certificate Thumbprint is. They will be longer than what if referenced with the X's.

$null = Connect-MgGraph -ClientID xxxxxxxxxxxxxx -TenantId xxxxxxxxxxxxxxxx -CertificateThumbprint xxxxxxxxxxxxxxxx -ErrorAction Stop
#$null = Connect-MgGraph -ClientID xxxxxxxxxxxxxx -TenantId xxxxxxxxxxxxxxxx -CertificateThumbprint xxxxxxxxxxxxxxxx -ErrorAction Stop

@SMSAgentSoftware
Copy link
Author

Hey all, as it seems a popular request I've updated the script to work for multiple computers without requiring re-authentication. Simply call the script providing multiple computer names in a string array, eg:

Delete-DeviceRecords -ComputerName @("PC001","PC002") ...

Or use a variable containing multiple names:

$ComputerNames = @(
"PC001"
"PC002"
)

Delete-DeviceRecords -ComputerName $ComputerNames ...

@HeroesBaneAdmin
Copy link

I am having issues launching the script with an array. What am I missing? It seems to error everytime on the second device in the array. Any advise, I am sure I am missing something simple. Here is what I have tried and the error I am getting:

Tried this (entered my actual computer names instead of the examples, but used same exact formatting):
$ComputerNames = @(
"PC001"
"PC002"
)
Ran this command from PS: powershell.exe -File C:\Scripts\Delete-DeviceRecords.ps1 -ComputerName $ComputerNames -All

and got this error (I replaced the computer name with the example one):
C:\Scripts\Delete-DeviceRecordsDev.ps1 : A positional parameter cannot be found that accepts argument 'PC002'.
+ CategoryInfo : InvalidArgument: (:) [Delete-DeviceRecordsDev.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Delete-DeviceRecords.ps1

The script works fine if I just specify an individual device like this: powershell.exe -File C:\Scripts\Delete-DeviceRecordsDev.ps1 -ComputerName PC002 -All

Thanks

@HeroesBaneAdmin
Copy link

HeroesBaneAdmin commented Nov 29, 2023

I am having issues launching the script with an array. What am I missing? It seems to error everytime on the secod device in the array. Any adive, I am sure I am missing something simple. Here is what I have tried and the error I am getting:

Tried this (entered my actual computer names instead of the examples, but used same exact formatting):
$ComputerNames = @(
"PC001"
"PC002"
)
Ran this command from PS: powershell.exe -File C:\Scripts\Delete-DeviceRecords.ps1 -ComputerName $ComputerNames -All

and got this error:
C:\Scripts\Delete-DeviceRecords.ps1 : A positional parameter cannot be found that accepts argument 'PC002'.
+ CategoryInfo : InvalidArgument: (:) [Delete-DeviceRecords.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Delete-DeviceRecords.ps1

The script works fine if I just specify an individual device like this:
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment