5 PowerShell functions to create a SCCM “trickle install” – i.e. X at a time.

If you look at this post, I describe a my idea of a SCCM trickle install – that is X number of machines at a time. Rather that have the install hit the whole collection at once, I wanted to hit just 20 a night. That way if there is an error, we can put the breaks on the deployment. We create dynamic collections that use a “NOT IN” SQL statement – this results in all the machines that are in the collection need the specific software. This script copies X at a time from that collection to new collection.

In the previous post, I run a VBScript that loops through the first 10 (or X) number of machines in the collection and add them to a new collection that contains the assigned advertisement. The next night, the script runs again, and the next 10 (or X) are copied (since the source collection is dynamic, the machines from the night before are removed).

I wanted to do the same thing, but I wanted to use PowerShell. First up, a function to find a Collection’s Id.

FUNCTION JBM-SCCM-GetCollection {
	Param([parameter(Mandatory = $true)]$CollectionName,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
	$QUERY="Select CollectionID from SMS_Collection WHERE Name = '$CollectionName'"
	Return $(Get-WmiObject -namespace $SCCMNameSpace -computer $SCCMServer -query $QUERY)
}

Next a function to find all the machines in a collection:

FUNCTION JBM-SCCM-GetCollectionMembers{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
	$QUERY="SELECT Name FROM SMS_FullCollectionMembership WHERE CollectionID = '$CollectionID'"
	Return $(Get-WmiObject -namespace $SCCMNameSpace -computer $SCCMServer -query $QUERY)
}

Next a function to remove all machines in a collection (the ones that are directly added)

FUNCTION JBM-SCCM-DeleteAllCollectionMembers{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
    $Collection=[WMI]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID='$CollectionID'"
	ForEach ($Rule in  $Collection.CollectionRules ){
    $Collection.DeleteMembershipRule($Rule)
    }
}

Next, a function to add a machine to a Collection:

FUNCTION JBM-SCCM-AddCollectionMember{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com",
    [parameter(Mandatory = $true)]$ComputerToAdd)
	$SCCMNameSpace="root\sms\site_$SiteName"

    $computer = gwmi -computer $SCCMServer -namespace $SCCMNameSpace -Query "select * from SMS_R_System where NetBiosName='$ComputerToAdd'"
    $Collection=[WMI]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID='$CollectionID'"
    $ruleClass = [wmiclass]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_CollectionRuleDirect"
    $newRule = $ruleClass.CreateInstance() 
    $newRule.RuleName = $ComputerToAdd 
    $newRule.ResourceClassName = "SMS_R_System" 
    $newRule.ResourceID = $computer.ResourceID 
    $null = $Collection.AddMembershipRule($newRule) 
}

Finally, a function to copy machines from one collection to another, using the functions above:

FUNCTION JBM-SCCM-CopyCollectionMembers {
Param([parameter(Mandatory = $true)]$SourceCollectionName,
    [parameter(Mandatory = $true)]$DestinationCollectionName,
    [parameter(Mandatory = $true)]$NumberToCopy)

    $SrcCollID=JBM-SCCM-GetCollection($SourceCollectionName)
    $DstCollID=JBM-SCCM-GetCollection($DestinationCollectionName)
    $SrcCollMembers=JBM-SCCM-GetCollectionMembers($SrcCollID.CollectionID)
    JBM-SCCM-DeleteAllCollectionMembers($DstCollID.CollectionID)
    foreach ($Computer in $($SrcCollMembers | select -first $NumberToCopy)){
    JBM-SCCM-AddCollectionMember -CollectionID $DstCollID.CollectionID -ComputerToAdd $Computer.Name
    }

}

The result – a trickle install.

,

6 Responses to 5 PowerShell functions to create a SCCM “trickle install” – i.e. X at a time.

  1. Tony September 29, 2012 at 5:16 am #

    HI,
    I need to connect server by remote, and also i have another admin account on that server not my local admin account.
    Other script i am connecting fine coz have used -Credential.
    This belowing part:
    $Collection=[WMI]”\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID=’$CollectionID'”
    $ruleClass = [wmiclass]”\\$($SCCMServer)\$($SCCMNameSpace):SMS_CollectionRuleDirect

    I am really stuck in here. It’s seems if i use [WMI] or [wmiclass] can not use -Credential.
    If i can’t use Credential here , Is there other solution , Actually my purpose is want to deploy software from client’s computer using SCCM.

    But

  2. jbmurphy October 1, 2012 at 12:02 pm #

    I have only run this on the server it self. I have not had much success running WMI queries against the server from a client workstation for use in a deployment scenario.

  3. Tony October 2, 2012 at 10:45 am #

    Thanks man anyway, it is really nice script that you wrote here, My little application is running well in the server. But i am still in eager to deploy SW’s from client side hehe i hope you understand me, I am still googling , i can not give up !

  4. Martin April 23, 2013 at 7:07 pm #

    If you have want to remove alle members you may use $Collection.DeleteMembershipRules()
    So you are able to avoid the for each loop:

    $Collection=[WMI]”\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID=’$CollectionID'”
    $Collection.DeleteMembershipRules($Collection.CollectionRules)

    does it in one step

  5. jbmurphy April 25, 2013 at 10:11 am #

    That seems easier.

Trackbacks/Pingbacks

  1. Using PowerShell to throttle your ConfigMgr software deployments - May 24, 2012

    […] Read the full post: 5 PowerShell functions to create a SCCM “trickle install” – i.e. X at a time […]