Jaa


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

Comments

  • Anonymous
    September 13, 2006
    Can I use a txt document with the list of 40 to 50 machines to delete?

  • Anonymous
    September 13, 2006
    You can either modify the script to accept a txt file instead of a single machine.  Any easy way to make this work would be to read each value from the txt file, set sDelClient to that value, then call the delete function(s) in a loop.  This isn't very efficient but would work.  A better, more time consuming option, would be to modify both of the delete client functions to accept an array of clients (that way you don't have a reconnect to WMI each time).

  • Anonymous
    December 07, 2006
    Hi, what will happen if I delete the entries in the SMS database like this "Delete from System_DISC where Name0 = '" "Delete from System_DATA where Name0 = "" THX

  • Anonymous
    December 12, 2006
    If you delete directly from the system_disc table then the entries will be removed from SMS, but there is a chance you might orphan some data for that client in the DB.  This really depends on how the triggers are setup on that table (haven't personally dug into this as it's not something we would recommend doing).  The more appropriate way to delete a client is through the console or the SDK.

  • Anonymous
    August 30, 2007
    Russ, one thing I was wondering was:- What would be the minimum security right that would allow a user to run this against a server?? Within SMS I see that the minimum requirement is a Class Security Right of Delete Resource against Collections. However, regarding NT security I can only seem to get it do work if I make the user running it a member of the local Administrators group. I've tried various other combinations e.g. adding user to "Distributed DCOM Users" or "Power Users", but haven't had any luck. The site server is running on Windows 2003 SP2. Other than that, its a wonderful script....

  • Anonymous
    August 30, 2007
    The comment has been removed

  • Anonymous
    August 30, 2007
    I tried doing it through dcomcnfg without luck.  However.... I think I have found a way to do it, but am not sure if it maybe exposed security too much. Computer Management (on site server)   Services and Applications      WMI Control Then add the required users to the SMS namespace (and subnamespaces). So the question would be, is this too unsecure?  What if this permission was given to "Domain Users"? My guess would be it is unsecure. But it would be extremely unlikely someone would connect to this mistakenly.

  • Anonymous
    August 30, 2007
    If you can connect to rootcimv2 (using the ConnectServer() and/or GetObject methods) and not to rootsmssite_<sitecode> then it shouldn't be a DCOM thing and the focus should be on SMS permissions.  Have you added the applicable user/group to the SMS Admins group on the server?  That should give you rights to the SMS namespace, then you'll need the class permissions you mentioned earlier.