Menu Close

Delete a large number of agents in SCOM from a text file

image

I have had this request from several customers, just want to document a PowerShell script example of this for the community.

Sometimes I have customers who end up with a large number of agents that are decommissioned, or we want to remove large numbers of agents because we migrated them to a different management group.  Sometimes we just need an automation example to use in a scripted decommission process.  In PowerShell, we don’t have a cmdlet to delete SCOM agents.  However, we do have a method we can leverage under ManagementGroupAdministration, called:  DeleteAgentManagedComputers

https://docs.microsoft.com/en-us/dotnet/api/microsoft.enterprisemanagement.administration.managementgroupadministration.deleteagentmanagedcomputers?view=sc-om-dotnet-2016

Here is a script example.  This is designed to be run on a SCOM management server locally, but can be modified to run remotely.

######################################################################## # Example: .\SCOMDeleteAgentsFromFile.ps1 -File "C:\temp\servers.txt" ######################################################################## param([string]$File) # If you want to hard code the path to the file # $File = "C:\temp\servers.txt" # Gather the start time of the script $StartTime = Get-Date #Clear the screen Clear-Host Write-Host `n"Starting Agent Delete Script" #Check to make sure we got some parameters IF (!($File)) { Write-Host `n"You must specify a full path to a file using the -File parameter to the script." Write-Host `n"Example: .\SCOMDeleteAgentsFromFile.ps1 -File ""C:\temp\servers.txt"""`n PAUSE EXIT } Write-Host `n"Full File Path: $File" Import-Module OperationsManager New-SCOMManagementGroupConnection -ComputerName Localhost # Load MG Administration object $MG = Get-SCOMManagementGroup $Admin = $MG.GetAdministration() #Get Server list Write-Host `n"Getting serverlist file content....." [array]$ServerList = Get-content $File IF (!($Serverlist)) { Write-Host `n"Getting serverlist file content FAILED"`n PAUSE EXIT } ELSE { $ServerlistCount = $ServerList.count Write-Host `n"Found ($ServerListCount) servers in serverlist file" } # Get all the Windows Computers into my Array Write-Host `n"Getting All Windows Computer objects in Management Group....." Write-Host `n"This can take a few minutes" [array]$WCarr = Get-SCOMClass -Name "Microsoft.Windows.Computer" | Get-SCOMClassInstance IF (!($WCArr)) { Write-Host `n"Getting all Windows Computer objects FAILED"`n PAUSE EXIT } ELSE { $WCCount = $WCArr.count Write-Host `n"Found ($WCCount) Windows Computer objects in Management Group" } # Create an empty Hashtable $HashTable = @{} # Fill the hashtable from the array using the unique FQDN as the Key FOREACH($WC in $WCarr) { $HashTable.Add("$($WC.DisplayName)",$WC) } #Start MM Loop Write-Host `n"Starting Agent Delete loop for servers in file....." FOREACH ($Server in $ServerList) { # Retrieve the individual matching object from the Hashtable $WCobj = $HashTable.($Server) IF (!($WCobj)) { Write-Host `n"Warning: $Server was not found as a Windows Computer object in SCOM. Skipping......"`n } ELSE { Write-Host `n"Deleting: $Server" $AMCguid = $WCobj.Id.Guid $query = [string]::Format("Id = '{0}'", $AMCguid.Trim()) #Create criteria for Agent Managed Computer $AMCCriteria = New-Object Microsoft.EnterpriseManagement.Administration.AgentManagedComputerCriteria($query) #Get Agent Managed Computer $AMCarr = ($Admin.GetAgentManagedComputers($AMCCriteria)) # Define generic collection list which is required parameter for the SDK delete command $AgentManagedComputerType = [Microsoft.EnterpriseManagement.Administration.AgentManagedComputer]; $GenericListType = [System.Collections.Generic.List``1] $GenericList = $GenericListType.MakeGenericType($AgentManagedComputerType) $AMCList = new-object $GenericList.FullName # Add each AMC in the array to the collection list FOREACH ($AMC in $AMCarr) { $AMCList.Add($AMC) } # Delete the agent in the collection $Admin.DeleteAgentManagedComputers($AMCList) } } #Log an event for script ending and total execution time. $EndTime = Get-Date $ScriptTime = ($EndTime - $StartTime).TotalSeconds Write-Host `n"Script Completed" Write-Host `n"Script Runtime: ($ScriptTime) seconds."`n #End of script

5 Comments

  1. Vicky

    Thanks for this, would be nice if you could come up with another variation (or built in) to remove Unix/Linux agents as well

  2. Andy Perry

    Thanks Kevin!

    Is there a way to catch any that fail to delete when the batch list is processed by the DeleteAgentManagedComputers?

    I can loop through the original $AMCList later checking if they have gone, but just wondering if any way to intercept during the batch job.

    Thank you

    Andrew

    • Andy Perry

      Also, apologies if I am mis-understanding…just trying to work through it all to learn and understand the flow.

      This looks like the call to the $Admin.DeleteAgentManagedComputers would run each time for each server in ServerList? Shouldn’t this just run once outside of the FOREACH loop?

      I assume the idea is to do a batch delete on all of the items in the $AMCList once. Or is it intentionally just deleting one at a time? If so, this might answer my first question 🙂

      Thanks

      Andrew

      • Kevin Holman

        I chose to do a FOREACH LOOP through each server in the list, and doing individual deletes instead of creating a large collection, then deleting the collection in batch. I have had issues with batch deletes in the past, so to try and see if this would result in fewer orphaned objects, I chose to not batch delete the collection, but call the delete for each computer individually. I am not sure which is more reliable, but the goal was to reduce an odd anomaly I see sometimes where some components of a computer get left behind using this method. I didn’t check with an Escalation Engineer who looked at the code, and deleting an agent from agent managed does exactly the same as this, so I felt this was MOST reliable, albeit a bit slower than a batch delete. Speed was not my goal, reduced orphans was.

Leave a Reply

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