How to delete an SMS client throughout your hierarchy

Remember delmif.exe in SMS 1.2? It was a nice utility used to delete machines throughout your entire hierarchy. In SMS 2003 resource deletions do not flow from child sites up the hierarchy. 

In SMS 2003 SP2 some improvements have been made to deal with this. Decommissioned DDRs now get created and sent to the parent site when a deletion occurs. This is not enabled by default.
To enable this feature, set the following registry value:

HKLM\Software\Microsoft\SMS\Components...
...\SMS_Discovery_Data_Manager:DecommissionNotification
to a value of 1.

You typically only want to use this feature on sites that require it (lower tier sites, only one per hierarchy branch recommended). When the parent site processes the decommissioned DDR the Decommissioned property in SMS_R_System class (System_DISC table) gets set from 0 to 1. You can then query and base collections on this property.

So what if this feature doesn't meet your needs or you don't have SP2? Well, you can manually delete the resources from each site in your hierarchy or run a script like the one attached against your central site and have it delete the resources in your hierarchy.

-Russ

 'Script Name: DelClient.vbs
'Script Author: Rslaten
'Script Purpose: Delete a client throughout hierarchy
'Script Creation Date: 04/01/2005
'Script Version: 1.1
'Revision History

'Ver    Date        Person    Description
'-----------------------------------------------------------------------------------------
'1.0    04/01/2005    rslaten    Created Script
'1.1    02/14/2006    rslaten    Added additional error checking to script

'Other Information

'Set globals
Dim sCenSiteServer, sDelClient, bEverywhere, sSMSCenNameSpace, SMSSites()

'Call to start program
Main

Sub Main
    GetCommandLineArguments
    sSMSCenNameSpace = GetSMSNameSpace(sCenSiteServer)
    If bEverywhere Then
        GetSiteList
        DelClientLoop
    Else
        DelSingleClient
    End If
End Sub

'Deletes single client
Sub DelSingleClient
    On Error Resume Next
    Dim oLocator, oServices, refItem, colClient
    Set oLocator = CreateObject("WbemScripting.SWbemLocator")
    WScript.Echo "Connecting to " &sCenSiteServer
    Set oServices = oLocator.ConnectServer(sCenSiteServer, sSMSCenNameSpace,,,,,128)
    If Err.number <> 0 Then
        WScript.Echo "Unable to connect to " &sCenSiteServer
        WScript.Echo Err.number & " - " &Err.Description
    Else
        Set colClient = oServices.ExecQuery("select * from SMS_R_System where NetbiosName =" _
            & " '" &sDelClient& "'")
        If colClient is Nothing or Err.Number <> 0 Then
            WScript.Echo  sDelClient& " doesn't exist at site " & sCenSiteServer
        Else
            For each refItem in colClient
                refItem.Delete_()
                If Err.number <> 0 Then
                    WScript.Echo "Failed to delete " &sDelClient& " on site " & sCenSiteServer
                    WScript.Echo Err.number & " - " & Err.Description
                Else
                    WScript.Echo "Successfully deleted " &sDelClient& " on site " & sCenSiteServer
                End If
            Next
        End If
    End If
    Set refItem = Nothing
    Set colClient = Nothing
    Set oServices = Nothing
    Set oLocator = Nothing
End Sub

'Delete clients
Sub DelClientLoop()
    On Error Resume Next
    Dim oLocator, oServices, Namespace, refItem, colClient
    Set oLocator = CreateObject("WbemScripting.SWbemLocator")
    
    For i = 0 to UBound(SMSSites)
        WScript.Echo "Connecting to " &SMSSites(i)
        Namespace = GetSMSNamespace(SMSSites(i))
        Set oServices = oLocator.ConnectServer(SMSSites(i), NameSpace,,,,,128)
        If Err.number <> 0 Then
            WScript.Echo "Unable to connect to " &SMSSites(i)
            WScript.Echo Err.number & " - " &Err.Description
        Else
            Set colClient = oServices.ExecQuery("select * from SMS_R_System where NetbiosName =" _ 
            &" '" &sDelClient& "'")
            If colClient is Nothing or Err.Number <> 0 Then
                WScript.Echo  sDelClient& " doesn't exist at site " & SMSSites(i)
            Else
                For each refItem in colClient
                    refItem.Delete_()
                    If Err.number <> 0 Then
                        WScript.Echo "Failed to delete " &sDelClient& " on site " & SMSSites(i)
                        WScript.Echo Err.number & " - " & Err.Description
                    Else
                        WScript.Echo "Successfully deleted " &sDelClient& " on site " & SMSSites(i)
                    End If
                Next
            End If
        End If
        Set refItem = Nothing
        Set colClient = Nothing
        Set oServices = Nothing
    Next
    Set oLocator = Nothing
End Sub

'Gets list of SMS Sites in the hierarchy
Sub GetSiteList()
    On Error Resume Next
    WScript.Echo "Getting list of SMS Primary Sites from " &sCenSiteServer
    Dim oLocator, oServices, colSites, refItem, i
    Set oLocator = CreateObject("WbemScripting.SWbemLocator")
    Set oServices = oLocator.ConnectServer(sCenSiteServer, sSMSCenNameSpace,,,,,128)
    If Err.number <> 0 Then
        WScript.Echo "Error connecting to " &sSMSCenNameSpace& " on " &sCenSiteServer& ": " _
        &Err.Number
        Set oLocator = Nothing
        Set oServices = Nothing
        WScript.Quit
    End If
    Set colSites = oServices.ExecQuery("select * from SMS_Site")
    For Each refItem in colSites
        If refItem.Type = "2" Then
            ReDim Preserve SMSSites(i)
            SMSSites(i) = refItem.ServerName
            i = i + 1
        End If
    Next    
    Set colSites = Nothing
    Set oLocator = Nothing
    Set oServices = Nothing
End Sub

'Gets SMS namespace
Function GetSMSNameSpace(SiteServer)
    On Error Resume Next
    Dim colNameSpaceQuery, refitem, refWMI
    Set refWMI = GetObject("winMgmts:\\" &SiteServer&"\root\sms")
    If Err.number <> 0 Then
        WScript.Echo "Error connecting to SMS namespace on " &SiteServer
        WScript.Quit
    End If
    Set colNameSpaceQuery = refWMI.ExecQuery("select * from SMS_ProviderLocation")
    For Each refitem in colNameSpaceQuery
        GetSMSNameSpace = refitem.NamespacePath
    Next
    Set colNameSpaceQuery = Nothing
    Set refitem = Nothing
    Set refWMI = Nothing
End Function

'Gets Command line args
Sub GetCommandLineArguments
    On Error Resume Next
    Dim iParameterCount
    iParameterCount = WScript.Arguments.Count
    If iParameterCount < 2 Then
        ShowHelp
        Bailout
    End If
    If iParameterCount = 2 Then
        bEverywhere = FALSE
    Else
        If Ucase(WScript.Arguments(2)) = "EVERYWHERE" Then
            bEverywhere = TRUE
        End If
    End If
    sCenSiteServer = WScript.Arguments(0)
    sDelClient = WScript.Arguments(1)
End Sub

'Routine for quiting script
Sub Bailout
    WScript.Quit
End Sub

'Displays syntax
Sub ShowHelp
    WScript.Echo ""
    WScript.Echo "DelClient v1.1"
    WScript.Echo "Usage: cscript.exe DelClient.vbs <CenSiteServerName> <NameOfClient> EVERYWHERE"
    WScript.Echo "Note, the EVERYWHERE parameter is optional."
    WScript.Echo "If EVERYWHERE is used then it will delete the client from each lower tier site."
    WScript.Echo "If EVERYWHERE is not used then this script will only delete from that server."
    WScript.Echo "Example: cscript.exe DelClient.vbs myCentralSiteServer myDeletedClient"
    WScript.Echo ""
End Sub

DelClient.zip