Tagged: Collection

Keep a list of user/computer groups in registry

In the migration to ConfigMgr 2012 we are aiming at just keeping one collection for software distribution and instead rely on global conditions.
We do want to keep the option to add a user to a group and with that do a automagic distribution.

So, the examples below are snippets from the logonscript.

Here is the short version:
– Recursive search for group membership for user
– If group-list changed, update the reg key
(Then do the same for computer groups)
– If there are any changes to groups, trigger the ConfigMgr agent

– Create a global condition in ConfigMgr
– Use the condition like “If MyGlobalCondition contains SwDistGroupName”

$userDN = "CN=MyUser,OU=Users,DC=snowland,DC=se"
$computerDN = "CN=CyComputer,OU=Computers,DC=snowland,DC=se"

Function Get-DistGroups {
	PARAM (
		$ObjectDN,
		$nameFilter = "SwDist_*"
	)

	$distGroups = @()
	$AdSearch=([ADSISearcher]"LDAP://")
	$AdSearch.pagesize=512
	$AdSearch.Filter="(&(member:1.2.840.113556.1.4.1941:=$($ObjectDN))(name=$($nameFilter)))"
	$AdSearch.findAll() | ForEach-Object {
		Write-Verbose "Found group: $($_.Properties.Item('Name'))"
		$distGroups += $_.Properties.Item("Name")
	}

	Return $distGroups
}

# Standard setting
$runConfigMgrActions = $false

# Store DIST groups in registry
Write-Host "Reading User DIST groups"
$userDistGroups = Get-DistGroups -ObjectDN $userDN | Sort-Object
$CurrKeys = Read-RegKey -Key "HKCU:\Software\SSAB\SoftwareDistribution" -Name "UserGroups" | Sort-Object
If ((Compare-Object -ReferenceObject $CurrKeys -DifferenceObject $userDistGroups) -ne $null) {
	Write-Host "Found added/removed user groups, writing new list to registry"
	New-ItemProperty "HKCU:\Software\snowland\SoftwareDistribution" -Name "UserGroups" -Value $userDistGroups -PropertyType "MultiString" -Force | Out-Null

	$runConfigMgrActions = $true
} else {
	Write-Verbose "No changes in user groups"
}

Write-Host "Reading computer groups"
$computerDistGroups = Get-DistGroups -ObjectDN $computerDN | Sort-Object
$CurrKeys = Read-RegKey -Key "HKLM:\Software\SSAB\SoftwareDistribution" -Name "ComputerGroups" | Sort-Object

If ((Compare-Object -ReferenceObject $CurrKeys -DifferenceObject $computerDistGroups) -ne $null) {
	Write-Host "Found added/removed computer groups, writing new list to registry"
	New-ItemProperty "HKLM:\Software\snowland\SoftwareDistribution" -Name "ComputerGroups" -Value $computerDistGroups -PropertyType "MultiString" -Force | Out-Null
	$runConfigMgrActions = $true
} else {
	Write-Verbose "No changes in computer groups"
}

# Trigger ConfigMgr client actions if groups have changed
If ($runConfigMgrActions -eq $true) {
	Write-Verbose "Changes to DIST groups, running ConfigMgr Actions"
	(New-Object -ComObject CPApplet.cpAppletMgr).GetClientActions() | Where-Object {$_.Name -like "Application Global Evaluation Task*" -or $_.Name -like "Request & Evaluate*"} | Sort-Object Name | ForEach-Object {
		Write-Host "Starting ConfigMgr action: $($_.Name)"
		$_.PerformAction()
	}
}

(To do this you need to set a security GPO to the HKLM-key so that your users are allowed to write there.)

Change Collection Refresh Rate

Had some problems with loads of collection refresh taking all of the CPU on the SCCM-server.

So first, to get the SCCM-server to calm down I wrote a small (and somewhat ugly, since it uses SQL) hack:

UPDATE Collections
Set Flags = 17
Where CollectionName LIKE '%Something In The Collection Name%'
AND Flags=18

This script uncheck the box “Update his collection on a schedule” for the collections.

Then, when the SCCM server did go back to a normal CPU-utilization we used this script to set another refresh-rate on the collections.

Const cSccmProvider = "."
Const cWmiUsername = ""
Const cWmiPassword = ""

Const cCollectionNamePattern = "%Something In The Collection Name%"
Const cDoUpdate = True		' Set to false to test
Const cRefreshDays = 0		' 0 - 31
Const cRefreshHours = 12	' 0 - 23
Const cRefreshMinutes = 0	' 0-59

Set oLocator = CreateObject("WbemScripting.SWbemLocator")

' --- Get SCCM Site Code
WScript.Echo "Connecting to: " & cSccmProvider
Set oSccmWmi = oLocator.ConnectServer(cSccmProvider, "root\sms", cWmiUsername, cWmiPassword)
Set oWmiQuery = oSccmWmi.ExecQuery("SELECT SiteCode FROM SMS_ProviderLocation WHERE ProviderForLocalSite=true")
For each currentSite in oWmiQuery
	sSccmSiteCode = currentSite.SiteCode
	Exit For
Next

' --- Connect to site
WScript.Echo "Connecting to: " & cSccmProvider &  " - root\sms\site_" & sSccmSiteCode
Set oSccmWmi = oLocator.ConnectServer(cSccmProvider, "root\sms\site_" & sSccmSiteCode, cWmiUsername, cWmiPassword)

' --- Create interval
WScript.Echo "Creating Interval: " & cRefreshDays & " days, " & cRefreshHours & " hours, " & cRefreshMinutes & " minutes."
Set oInterval = oSccmWmi.Get("SMS_ST_RecurInterval")  
oInterval.DaySpan = cRefreshDays
oInterval.HourSpan = cRefreshHours
oInterval.MinuteSpan = cRefreshMinutes
oInterval.isGmt = False
oInterval.StartTime = "20090101000000.000000+***"

' --- List all collection
set oCollections = oSccmWmi.ExecQuery("SELECT * FROM SMS_Collection WHERE Name LIKE '" & cCollectionNamePattern & "'")
For Each oCollection In oCollections
	' --- Update interval on Collection
	If cDoUpdate Then
		WScript.Echo "Updating: " & oCollection.CollectionID & " - " & oCollection.Name
		Set oCollectionToChange = oSccmWmi.Get("SMS_Collection.CollectionID='"  & oCollection.CollectionID & "'")
		oCollectionToChange .RefreshSchedule = Array(oInterval)
		oCollectionToChange .RefreshType = 2  '1 = Manual, 2 = Periodic refresh
		oCollectionToChange .Put_
	Else
		WScript.Echo "Testing: " & oCollection.CollectionID & " - " & oCollection.Name
	End if
Next

The script is attached here: changeCollectionRefresh.vbs

Clients missing inventory

I’m trying to figure out why some clients are missing the inventory in add/remove programs…
So I made a nice little collection with a query that only shows clients missing the inventory.

SELECT *
FROM SMS_R_System
WHERE
	SMS_R_System.ResourceId NOT IN (SELECT ResourceID FROM SMS_G_System_ADD_REMOVE_PROGRAMS)
	AND Client = 1