widsnet.com
20Dec/170

Check if IP is between range (Boundaries)

Check if an IP address is inside an existing boundary.

$SiteServer = ""
$SiteCode = ""

Function Get-MatchingBoundary {
    Param(
    [parameter(Mandatory=$true)]$Boundaries,
    [parameter(Mandatory=$true)]$IPAddress)

    $Result = 0

    ForEach ($Boundary in $AllBoundaries) {
        $BoundaryName = $Boundary.DisplayName
        $IPRangeStart, $IPRangeEnd = $Boundary.Value.Split("-")

        $ParseIP = [System.Net.IPAddress]::Parse($IPAddress).GetAddressBytes()
        [Array]::Reverse($ParseIP)
        $ParseIP = [System.BitConverter]::ToUInt32($ParseIP, 0)

        $ParseIPStart = [System.Net.IPAddress]::Parse($IPRangeStart).GetAddressBytes()
        [Array]::Reverse($ParseIPStart)
        $ParseIPStart = [System.BitConverter]::ToUInt32($ParseIPStart, 0)

        $ParseIPEnd = [System.Net.IPAddress]::Parse($IPRangeEnd).GetAddressBytes()
        [Array]::Reverse($ParseIPEnd)
        $ParseIPEnd = [System.BitConverter]::ToUInt32($ParseIPEnd, 0)

        if (($ParseIP -ge $ParseIPStart) -and ($ParseIP -le $ParseIPEnd)) {
            if ($BoundaryName.Length -ge 1) {
                $Results = 1
                Write-Output "$IPAddress is within: $BoundaryName"
            }
            else {
                $Results = 1
                Write-Output "$IPAddress is within: Range $($Boundary.Value)"
            }
        }
    }
    if ($Results -eq 0) {
        Write-Output "$IPAddress is not in any boundary"
    }
}

[Net.IPAddress]$IPaddress = "10.89.184.85"

# Get all boundaries from SCCM
$AllBoundaries = Get-WMIObject -computer "$SiteServer" -Namespace "Root\SMS\Site_$SiteCode" -Class "SMS_Boundary" -Filter "BoundaryType = 3"

Get-MatchingBoundary -Boundaries $AllBoundaries -IPAddress $IPaddress
20Oct/170

Run client actions with vbs

' Set the required variables.
sSoftwareMetering = "Software Metering Usage Report Cycle"
sMachinePolicy = "Request & Evaluate Machine Policy"
sUpdatesSource = "Updates Source Scan Cycle"
sUserPolicy = "Request & Evaluate User Policy"
sHardwareInventory = "Hardware Inventory Collection Cycle"
sSoftwareInventory = "Software Inventory Collection Cycle"
sApplicationEvaluation = "Application Global Evaluation Task"
sSoftwareUpdates = "Software Updates Assignments Evaluation Cycle"
sDiscoveryData = "Discovery Data Collection Cycle"
sMSISourceUpdate = "MSI Product Source Update Cycle"
sFileCollection = "Standard File Collection Cycle"

' Create the CPAppletMgr instance.
Set controlPanelAppletManager = CreateObject("CPApplet.CPAppletMgr")

' Get the available ClientActions object.
Set clientActions = controlPanelAppletManager.GetClientActions()

' Loop through the available client actions. Run the matching client action when it is found.
For Each clientAction In clientActions
    If clientAction.Name = sUpdatesSource Then
        clientAction.PerformAction
    ElseIf clientAction.Name = sSoftwareUpdates Then
    	clientAction.PerformAction
    End If
Next
22Aug/170

Offline servicing fails with error 2095

The solution can be found here: http://www.syswow64.co.uk/2015/12/sccm-2012-r2-offline-servicing-error.html
Basically its the wim file that wants to reboot.

dism /mount-wim /wimfile:C:\temp\install.wim /index:1 /mountdir:c:\temp\mount

reg load HKLM\MyKey c:\temp\mount\windows\system32\config\software
regedit

Find the registry key
HKLM\MyKey\Microsoft\Windows\CurrentVersion\Compnent Based Servicing\SessionsPending
Take ownership of root Key
Assign Full Control to Administrator
Edit the DWORD Exclusives to value 0 (in my case it was 3)

Unload the registry
reg unload HKLM\MyKey

Commit the changes to the wim
dism /unmount-wim /mountdir:c:\temp\mount /commit

9Jun/170

Find collections with both incremental and full update

Since using incremental and full on a collection is completely useless, remove one or the other. This is one way to find the collections.
RefreshType
1 MANUAL
2 PERIODIC
4 CONSTANT_UPDATE
so RefreshType=6 is both.
https://msdn.microsoft.com/en-us/library/hh442671.aspx

$NameSpace = "root\sms\site_"

Function Get-Container() {
    Param(
        [string]$ContainerID,
        [string]$NameSpace
    )
    $Path = ""
    $Container = Get-WmiObject -Query "SELECT Name,ParentContainerNodeID FROM SMS_ObjectContainerNode WHERE ContainerNodeID='$ContainerID'" -Namespace $NameSpace
    If($Container.ParentContainerNodeID -ne 0) {
        $path += Get-Container -ContainerID $Container.ParentContainerNodeID -NameSpace $NameSpace
    }
    "$path\$($Container.Name)"
}

$Colls = Get-WmiObject -Query "SELECT CollectionID,Name FROM SMS_Collection WHERE RefreshType=6" -Namespace $NameSpace
Foreach ($Coll in $Colls) {
    $Container = Get-WmiObject -Query "SELECT ContainerNodeID FROM SMS_ObjectContainerItem WHERE InstanceKey='$($Coll.CollectionID)'" -Namespace $NameSpace

    If($Container -eq $null) {
        Write-Host "\$($Coll.Name)"
    }
    Else {
        $Container | ForEach-Object{
        $Parent = Get-Container -ContainerID $_.ContainerNodeID -NameSpace $NameSpace
        Write-Host "$Parent\$($Coll.Name) ($($Coll.CollectionID))"
        }
    }
}

20Apr/170

Create regvalues from TS variables

script to add in a TS to save certain task sequence variables to the registry, for whatever reason ...
Syntas looks like this. First argument is the start name of the variables. Second argument is the registry key to store the variables:
cscript CreateRegvaluesFromTSVariables.vbs "PostTS" "Software\HM\PostTSInstall"

Const HKEY_LOCAL_MACHINE = &H80000002

Set oRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
Set oArguments = WScript.Arguments

If oArguments.Count <> 2 Then
	WScript.Echo "Usage:"
	WScript.Echo "cscript " & Wscript.ScriptName & " ""variableName"" ""RegKey"""
	WScript.Echo " variableName" & vbTab & "Ex: ""HM"" if TS variables are Called HMIPNetmask and HMIPServer"
	WScript.Echo " RegKey" & vbTab & "Ex: Software\HM\ (Always under HKLM)"
	WScript.Echo ""
	WScript.Echo "The name after variableName will be created in the registry under RegKey with the value specified for the variable."
	WScript.Echo "Ex: If Task Sequence Variable HMIPNetmask is set to 255.255.255.0"
	WScript.Echo """IPNetMask"" will be created as a string under RegKey with Value ""255.255.255.0"""
	WScript.Quit 10022 'An invalid argument was supplied.
End If

sVariable = oArguments.Item(0)
sRegKey = oArguments.Item(1)

CreateKey(sRegKey)

'Gather OSD Variables and create registry values
Set osdVar = CreateObject("Microsoft.SMS.TSEnvironment")  
For Each sVar in osdVar.GetVariables() 
	If LCase(Left(sVar, Len(sVariable))) = LCase(sVariable) Then
		sValueName = Replace(sVar, sVariable, "", 1, 1, vbTextCompare)
		sValue = osdVar(sVar)
		If sValue <> "" Then
			CreateStringValue sRegKey, sValueName, sValue
		End if
	End If
Next

Sub CreateKey(sRegKey)
	oRegistry.CreateKey HKEY_LOCAL_MACHINE, sRegKey
End Sub

Sub CreateStringValue(sRegKey, sValueName, sValue)
	oRegistry.SetStringValue HKEY_LOCAL_MACHINE, sRegKey, sValueName, sValue
End Sub
20Apr/170

Syncronize time in a task sequence

Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject("Wscript.Shell")
Set objOSDEnv = CreateObject("Microsoft.SMS.TSEnvironment")
sLogPath = objOSDEnv("_SMSTSLogPath")

sLogFileName = Replace(WScript.ScriptName, ".vbs", ".log")
logThis "LogFile: " & sLogPath & "\" & sLogFileName

sUser = objOSDEnv("_SMSTSReserved1-000")
sPassword = objOSDEnv("_SMSTSReserved2-000")

logThis "%comspec% /c NET USE \\SERVER\IPC$ """ & "<password>" & """ /USER:" & sUser
Set oExec = oShell.Exec("%comspec% /c ""NET USE \\SERVER\IPC$ " & sPassword & " /USER:" & sUser & """")
logThis oExec.StdOut.ReadAll
logThis oExec.StdErr.ReadAll

logThis "%comspec% /c NET TIME \\SERVER /SET /Y"
Set oExec = oShell.Exec("%comspec% /c NET TIME \\SERVER /SET /Y")
logThis oExec.StdOut.ReadAll
If oExec.StdErr.ReadAll <> "" Then
	logThis oExec.StdErr.ReadAll
	wscript.quit(3912)
End If


Sub logThis(strText)
	'Create (if it doesn't exist) and open the logFile for appending
	Set oLogFile = objFSO.OpenTextFile(sLogPath & "\" & sLogFileName, ForAppending, True, 0)
	oLogFile.WriteLine(strText)
	oLogFile.Close	
End Sub
8Oct/150

Make a row red in Report Builder

This is a quick code snip to color a row red in Report builder based on the value in a field. In this case when the ExitCode isn't 0. I use it when checking the OS Installation Status of a Task Sequence. This code also keeps all the other rows colored the default way, gray/white.

=Switch(Fields!ExitCode.Value <> 0, "Tomato",
RowNumber(Nothing) Mod 2 = 0, "Transparent",
RowNumber(Nothing) Mod 2 = 1, "Gainsboro")
23Sep/150

Remove duplicates in SCCM 2012 based on Name

Simple script that should be scheduled to run on the primary server as the System account. Will fetch all dupliacte objects from ConfigMgr and sort them basen on ResourceID. It will always keep the latest object and delete the ones with older/lower ResourceID.

' This script removes all duplicates in SCCM (based on name)
' Always keeps the object with highest ResourceID (newest)

'Global constants
Const ForReading = 1, ForWriting = 2, ForAppending = 8

strComputer = "SERVER"
strNameSpace = "root\sms\site_SITECODE"

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject("Shell.Application")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\" & strNameSpace)

logThis "Start of script. Query WMI for duplicate computer objects"
' Get all duplicate objects from SCCM. Sort on computername and newest to oldest (highest ResourceID first)
Set colSettings = objWMIService.ExecQuery("SELECT DISTINCT r.* FROM SMS_R_System AS r FULL JOIN SMS_R_System AS s1 ON s1.ResourceId=r.ResourceId FULL JOIN SMS_R_System AS s2 ON s2.Name=s1.Name WHERE s1.Name=s2.Name AND s1.ResourceId!=s2.ResourceId ORDER BY r.Name, r.ResourceID DESC")
sName = ""
logThis "Found " & colSettings.Count & " objects"
For Each objResource in colSettings
	If sName = objResource.Name Then
		' Delete the old object!
		logThis "Deleting Name: " & objResource.Name & "; ResourceID: " & objResource.ResourceID & "; Client: " & objResource.Client & "; Active: " & objResource.Active & "; MAC: " & Join(objResource.Macaddresses, ",")
		iReturn = DeleteComputer(objWMIService, objResource.ResourceID)
		logThis "Return Code: " & iReturn
		WScript.Sleep 30000
		If sMAC = "" And UBound(objResource.Macaddresses) = 0 Then
			logThis "Save the MAC from this object to the newer object"
			iResourceID = UpdateMAC(objWMIService, objResource.Name, objResource.Macaddresses(0))
			logThis "MAC: " & objResource.Macaddresses(0) & " saved to ResourceID: " & iResourceID
		End If
	Else
		' Keep this one (highest ResourceID) and delete the ones to follow!
		sName = objResource.Name
		sMAC = Join(objResource.Macaddresses, ",")
		logThis "Keeping Name: " & objResource.Name & "; ResourceID: " & objResource.ResourceID & "; Client: " & objResource.Client & "; Active: " & objResource.Active & "; MAC: " & sMAC
   	End If
Next
logThis "End of script"

Function DeleteComputer(objWMIService, sResourceID)
	' Deletes a computer from SCCM
	On Error Resume Next
	Set oResource = objWMIService.Get("SMS_R_System.ResourceID='" & sResourceID & "'")
	oResource.Delete_
	DeleteComputer = Err.Number
End Function

Function UpdateMAC(objWMIService, netBiosName, macAddress)
	' Obtain an InParameters object specific
	' to the method.
	Set siteClass = objWMIService.Get("SMS_Site")
	Set inParams = siteClass.Methods_("ImportMachineEntry").inParameters.SpawnInstance_()
	
	' Add the input parameters.
	inParams.Properties_.Item("MACAddress") = macAddress
	inParams.Properties_.Item("NetbiosName") = netBiosName
	inParams.Properties_.Item("OverwriteExistingRecord") = True
	inParams.Properties_.Item("SMBIOSGUID") = Null
	
	' Add the computer.
	Set outParams = objWMIService.ExecMethod("SMS_Site", "ImportMachineEntry", inParams)
	UpdateMAC = outParams.ResourceID
End Function

Sub logThis(sText)
	Const CommonAppData = &H23&
	sNow = Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & " " & Right("0" & Hour(Now), 2) & ":" & Right("0" & Minute(Now), 2)
	sLogFilePath = oShell.Namespace(CommonAppData).Self.Path & "\Company\" & Replace(WScript.ScriptName, ".vbs", ".log", 1, 1, vbTextCompare)
	If oFSO.FolderExists(oFSO.GetParentFolderName(sLogFilePath)) = False Then
		oFSO.CreateFolder(oFSO.GetParentFolderName(sLogFilePath))
	End If
	Set oLogFile = oFSO.OpenTextFile(sLogFilePath, ForAppending, True)
	oLogFile.WriteLine(sNow & " " & sText)
	oLogFile.Close
End Sub
4Sep/140

How to join in WQL/WMI

Everyone knows that there is no "join" in WQL. But this is how you do it 🙂

SELECT SMS_Collection.Name,SMS_Collection.CollectionID 
FROM SMS_ObjectContaineritem,SMS_collection 
WHERE SMS_ObjectContaineritem.ContainerNodeId='16777224' 
AND SMS_Collection.CollectionID=SMS_ObjectContaineritem.InstanceKey 
ORDER BY SMS_Collection.Name ASC
22Jul/140

Nice to have CM2012 vbscripts

Some of these are only slighlty modified from CM SDK. Others are very modified 🙂
Response.Write is for ASP, replace it with Wscript.Echo to use in a script.

First. Connect to CM.

' Set connection = ConnectToCM
Function ConnectToCM
	' Make the connection to CM. Uses constants for servername, username and password
	' Also kind of from the CM SDK. A bit modified
    On Error Resume Next
    Set swbemLocator = CreateObject("WbemScripting.SWbemLocator")
    swbemLocator.Security_.AuthenticationLevel = 6 'Packet Privacy
    
    ' Connect to the server.
    Set swbemServices= swbemLocator.ConnectServer(sCMServer, "root\sms", sCMUser, sCMPassword)
    If Err.Number<>0 Then
        Response.Write "Couldn't connect: " + Err.Description
        Set ConnectToCM = null
        Exit Function
    End If

    ' Determine where the provider is and connect.
    Set providerLoc = swbemServices.InstancesOf("SMS_ProviderLocation")
	For Each location In providerLoc
		If location.ProviderForLocalSite = True Then
			Set swbemServices = swbemLocator.ConnectServer(location.Machine, "root\sms\site_" + location.SiteCode,sCMUser,sCMPassword)
			If Err.Number<>0 Then
				Response.Write "Couldn't connect:" + Err.Description
				Set ConnectToCM = Null
				Exit Function
			End If
			Set ConnectToCM = swbemServices
			Exit Function
		End If
	Next
    Set ConnectToCM = null ' Failed to connect.
End Function

Start with import a new computer. Returns the ResourceID for the new object.

Function AddNewComputer(connection, netBiosName, smBiosGuid, macAddress)
	' Import a new computer into CM. Based on function from CM SDK
	' Returns the ResourceID for the new object
	If (IsNull(smBiosGuid) = True) And (IsNull(macAddress) = True) Then
		Response.Write "smBiosGuid or macAddress must be defined"
		AddNewComputer = False
		Exit Function
	End If     

	If IsNull(macAddress) = False Then
		macAddress = Replace(macAddress,"-",":")
	End If    

	' Obtain an InParameters object specific
	' to the method.
	Set siteClass = connection.Get("SMS_Site")
	Set inParams = siteClass.Methods_("ImportMachineEntry").inParameters.SpawnInstance_()

	' Add the input parameters.
	inParams.Properties_.Item("MACAddress") =  macAddress
	inParams.Properties_.Item("NetbiosName") =  netBiosName
	inParams.Properties_.Item("OverwriteExistingRecord") =  False
	inParams.Properties_.Item("SMBIOSGUID") =  smBiosGuid

	' Add the computer.
	Set outParams = connection.ExecMethod("SMS_Site","ImportMachineEntry", inParams)
	AddNewComputer = outParams.ResourceID
End Function

Create a dynamic collection. Returns the CollectionID for the collection.

'sCollectionID = CreateDynamicCollection(connection, sCollName, sComment, True, "SELECT * FROM SMS_R_System WHERE Name LIKE '" & sCountry & "%'", sCollComment, sLimitingCollection)
Function CreateDynamicCollection(connection, newCollectionName, newCollectionComment, ownedByThisSite, queryForRule, ruleName, limitToCollectionID)
	' Function from CM SDK, slightly modified
    ' Create the collection.
    Set newCollection = connection.Get("SMS_Collection").SpawnInstance_
    newCollection.Name = newCollectionName
    newCollection.Comment = newCollectionComment
    newCollection.OwnedByThisSite = ownedByThisSite
    newCollection.LimitToCollectionID = limitToCollectionID
    
    ' Save the new collection and save the collection path for later.
    Set collectionPath = newCollection.Put_    
	
    ' Create a new collection rule object for validation.
    Set queryRule = connection.Get("SMS_CollectionRuleQuery")
    
    ' Validate the query (good practice before adding it to the collection). 
    validQuery = queryRule.ValidateQuery(queryForRule)
    
    ' Continue with processing, if the query is valid.
    If validQuery Then
        ' Create the query rule.
        Set newQueryRule = QueryRule.SpawnInstance_
        newQueryRule.QueryExpression = queryForRule
        newQueryRule.RuleName = ruleName
        
        ' Add the new query rule to a variable.
        Set newCollectionRule = newQueryRule
        
        ' Get the collection.
        Set newCollection = connection.Get(collectionPath.RelPath)
        
        ' Add the rules to the collection.
        newCollection.AddMembershipRule newCollectionRule
		
        ' Call RequestRefresh to initiate the collection evaluator.
        newCollection.RequestRefresh True
    End If
	CreateDynamicCollection = newCollection.CollectionID
End Function

Perhaps get the ID of a Folder, based on the name, to put the new collection in.

Function GetCollectionFolderID(connection, sName)
	' Returns FolderID for a folder under "Device Collections" based on Name
	Set oNodeID = connection.ExecQuery("SELECT * FROM SMS_ObjectContainerNode WHERE Name='" & sName & "' AND ObjectType='5000'") '5000 for SMS_Collection_Device
	If oNodeID.Count = 1 Then
		GetCollectionFolderID = oNodeID.ItemIndex(0).ContainerNodeID
	Else
		GetCollectionFolderID = ""
	End If
End Function

Move the collection to the folder.

Sub MoveCollectionToFolder(connection, CollectionID, TargetFolderID)
	ObjectType = 5000 '5000 is SMS_Collection_Device
	SourceFolderID = 0 ' Root folder
	On Error Resume Next
	' Move one collection. 
	sourceItems = Array(CollectionID)
	Set objInstance = connection.Get("SMS_ObjectContainerItem")
	
	' Set up the in parameters 
	Set objInParam = objInstance.Methods_("MoveMembers").inParameters.SpawnInstance_() 
	objInParam.Properties_.Item("InstanceKeys") = sourceItems 
	objInParam.Properties_.Item("ContainerNodeID") = SourceFolderID 
	objInParam.Properties_.Item("TargetContainerNodeID") = TargetFolderID 
	objInParam.Properties_.Item("ObjectType") = ObjectType
	
	' Call the method. 
	Set objOutParams = connection.ExecMethod("SMS_ObjectContainerItem","MoveMembers",objInParam)
End Sub

Create a new variable on the collection.

Sub CreateCollectionVariable(connection, name, value, mask, collectionId, precedence)
	' Sub from CM SDK
	' See if the settings collection already exists. if it does not, create it.
	Set settings = connection.ExecQuery("Select * From SMS_CollectionSettings Where CollectionID = '" & collectionID & "'")
	
	If settings.Count = 0 Then
		'Response.Write "Creating collection settings object"
		Set collectionSettings = connection.Get("SMS_CollectionSettings").SpawnInstance_
		collectionSettings.CollectionID = collectionId
		collectionSettings.Put_
	End If  
	
	' Get the collection settings object.
	Set collectionSettings = connection.Get("SMS_CollectionSettings.CollectionID='" & collectionId &"'" )
	
	' Get the collection variables.
	collectionVariables = collectionSettings.CollectionVariables
	
	' Create and populate a new collection variable.
	Set collectionVariable = connection.Get("SMS_CollectionVariable").SpawnInstance_
	collectionVariable.Name = name
	collectionVariable.Value = value
	collectionVariable.IsMasked = mask
	
	' Add the new collection variable.
	ReDim Preserve collectionVariables (UBound (collectionVariables)+1)
	Set collectionVariables(UBound(collectionVariables)) = collectionVariable
	collectionSettings.CollectionVariables=collectionVariables
	collectionSettings.Put_
End Sub

Get the collectionID based on name.

Function GetCollectionID(sName)
	' Return CollectionID based on Name
	Set oCollection = connection.ExecQuery("SELECT * FROM SMS_Collection WHERE Name='" & sName & "'")
	If oCollection.Count > 0 Then
		GetCollectionID = oCollection.ItemIndex(0).CollectionID
	Else
		GetCollectionID = ""
	End If
End Function

Add computer to a collection with direct membership.

Function AddComputerToCollection(connection, sResourceID, sCollectionID)
	' Add a computer to a collection with direct membership
	On Error Resume Next
	set collection = connection.Get("SMS_Collection.CollectionID='" & sCollectionID & "'")
	set collectionRule = connection.Get("SMS_CollectionRuleDirect").SpawnInstance_

	collectionRule.ResourceClassName = "SMS_R_System"
	collectionRule.ResourceID = sResourceID
	collection.AddMembershipRule collectionRule
	
	AddComputerToCollection = Err.Number
End Function

Two functions to get the ResourceID or the Computername, based on the other OR MAC.

Function GetResourceID(connection, sComputernameOrMAC)
	' Returns the ResourceID for a computer based on MAC or Name
	Set oResource = connection.ExecQuery("SELECT ResourceID FROM SMS_R_System WHERE Name='" & sComputernameOrMAC & "' OR MACAddresses='" & sComputernameOrMAC & "'")
	If oResource.Count > 0 Then 
		GetResourceID = oResource.ItemIndex(0).ResourceID
	Else
		GetResourceID = False
	End If
End Function

Function GetComputername(connection, sResourceIdOrMAC)
	' Returns the computername for a computer based on MAC or ResourceID
	Set oResource = connection.ExecQuery("SELECT Name FROM SMS_R_System WHERE ResourceID LIKE '" & sResourceIdOrMAC & "' OR MACAddresses='" & sResourceIdOrMAC & "'")
	If oResource.Count > 0 Then 
		GetComputername = oResource.ItemIndex(0).Name
	Else
		GetComputername = False
	End If
End Function

Clear last PXE Advertisement for a computer to be able to PXE boot the ocmputer again.

Function ClearPxeAdvertisementResource(connection, sResourceID)
	On Error Resume Next
	' Set up the Resource array parameter.
	resources = Array(1)
	resources(0) = sResourceID

	Set InParams = connection.Get("SMS_Collection").Methods_("ClearLastNBSAdvForMachines").InParameters.SpawnInstance_
	InParams.ResourceIDs = resources
	connection.ExecMethod "SMS_Collection", "ClearLastNBSAdvForMachines", InParams
	
	ClearPxeAdvertisementResource = Err.number
End Function

Is the computer already a member of a collection?

Function IsMemberOfCollection(connection, sCollID, sResourceID)
	' Check if ResourceID is member of CollectionID
	Set oExist = connection.ExecQuery("SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='" & sCollID & "' AND ResourceID='" & sResourceID & "'")
	If oExist.Count = 1 Then
		IsMemberOfCollection = True
	Else
		IsMemberOfCollection = False
	End If
End Function

Check for valid IP/Subnet/netmask and MAC syntax.

Function isValidIP(sIP)
	' not really ... just checking that the value is between 1.0.0.0 and 255.255.255.255
	' That way this function works for IP, Subnet and Netmask instead of having 3 different functions
	Set regEx = New RegExp
	regEx.Pattern = "^([1-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])([.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])){3}$"
	regEx.IgnoreCase = True
	isValidIP = regEx.Test(sIP)
End Function

Function isValidMAC(sMAC)
	' Syntax: XX:XX:XX:XX:XX:XX
	Set regEx = New RegExp
	regEx.Pattern = "^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$"
	regEx.IgnoreCase = True
	isValidMAC = regEx.Test(sMAC)
End Function

And last, delete the computer object.

Function DeleteComputer(connection, sResourceID)
	' Deletes a computer from SCCM
	On Error Resume Next
	Set oResource = connection.Get("SMS_R_System.ResourceID='" & sResourceID  & "'")
	oResource.Delete_
	DeleteComputer = Err.Number
End Function