SCCM Powershell Tools

, , , , ,

I’ll get this out of the way right now: I think SCCM’s PowerShell module is garbage.  It’s slow, it doesn’t work like you’d expect a lot of the time, and it’s got absolutely nothing on the ease of use and functionality of something like the ActiveDirectory module.  Thankfully, WMI is still a thing, and that gives us an excellent way to interact with SCCM via PowerShell. With that in mind, here’s some quick and dirty (but still useful) PowerShell functions I’ve put together. Most, if not all, PowerShell tools I’ve written for SCCM can also be done with SQL queries and commands, so if that’s more your thing, have at.

Find-ClientByMac
File can be downloaded from my technet gallery here
This is a simple enough tool. It will find any clients in the SCCM database that match a “like” query against the MAC address you provide.  This is handy for finding duplicate objects with the same MAC, which can royally screw with trying to PXE boot and image a computer.

Function Find-ClientByMAC ($inputMac){
$namespace = “root/SMS/Site_TST”
$siteServer = “testServer”

    $inputMac = $inputMac.Replace(” “,””)
$inputMac = $inputMac.replace(“-“,”:”)

if ($inputMac -notlike “*:*”)
{
$count = 0
while ($count -lt ($inputMac.Length – 2))
{
$inputMac = $inputMac.Insert(($count)+2,’:’)
$count += 3
}
$inputMac
}
Get-WmiObject -Namespace $namespace -ComputerName $siteServer -class SMS_R_System -filter “MACAddresses like ‘%$inputMac%'”
}


Something to keep in mind with SCCM is that it stores MAC addresses with “:” between each pair, but your computer’s IPConfig command will give it to you with “-“‘s.  This will replace a – with a :, and if you just feed it a straight set of text, it will insert the “:” between each pair.
This will find any computer that matches the MAC you provided and returns with a WMI object of the SMS_Device class.  If you want to delete the duplicate objects, you can simply pipe to the remove-wmiobject command to delete.

 

ALSO CHECK : N-2 WIM and Task Sequence Managment

Finding Empty Device Collections in SCCM

, , , , , , , ,

Today’s script is going to be almost a one-liner, but a very useful one.  I had found SQL queries that would do this same thing, but I frequently find myself working on a computer that does not have the SQL management software installed on it, and this query doesn’t run cleanly through the SCCM Management software.  However, I’m always on a computer with PowerShell and since this runs through WMI, you don’t even need to connect to the SCCM site code drive.
Having the right amount of device collections in SCCM is a bit of a balancing act. You don’t want so few collections that you don’t have a good way to sort out your clients logically, but you don’t want so many that you’ve gunked up your database with entries you’re never actually going to use. On top of that, some of the companies I’ve contracted with have had many collections that never held a single client. This script will go through and find those empty collections for you.   If you just want the PS1 file, click HERE.

Step 1: Initializing a few variables
Typically, if I’m working with SCCM through WMI, I like to setup a few variables in my shell right away to make my life easier and save some keystrokes throughout the day.
$siteServer = “PriServer1″ # whatever the name of your primary server is
$namespace = “root/SMS/site_TST” # root/SMS/site_  whatever your site code is

If you’re constantly making WMI calls to SCCM, being able to just enter those variables instead of typing it all out can make things easier. At least, that’s what I’ve found.

Step 2: Get your SCCM Device Collections
This script is going to be done on a single line, but I’ll break it out into chunks first. The first thing we need to do is pull all of the device collections from SCCM.
Get-WmiObject -Namespace $namespace -ComputerName $siteServer -Class SMS_Collection -filter ‘CollectionType =2’
 
If you wanted to pull user collections, you would change ‘CollectionType = 2’ to ‘CollectionType = 1’
If you want to get both sets of collections, just leave out the -filter portion entirely.

Step 3: Check Those Collections for Members
There are a couple ways you could do this. You could pipe your collections to a ForEach loop with an if statement in it. Alternatively, I choose to just pipe the first cmdlet into a where statement that does it for me.
| where {$colID = $_.CollectionID;(Get-WmiObject -Namespace $namespace -ComputerName $siteServer -class SMS_FullCollectionMembership -filter “CollectionID=’$colID'”).count -eq 0}

What this is doing is setting a variable called “$colID” to be the collection ID number from the collection passed through the pipe.  Then, we’re going to do a WMI query to the SMS_FullCollectionMembership class, which is a class that maintains a list of every device/user to collection association. We’re adding a filter to only show collection IDs that match the one we want, counting up all the members, and if that number equals 0, we know the collection has nothing in it.

Step 4: Profit
If you just stop there, you have a set of list-formatted data that, while not pretty, does contain all the information and objects you need to do work. It’s not the easiest thing to read, but it does give you a very solid information dump about the empty collection that looks something like this:

device collections

 

Chances are, if you’re generating this report for a manager, customer, etc, they’re going to want it formatted a bit nicer, and they’ll probably want it in an Excel spreadsheet.  The easiest way to do this is:
| select Name,CollectionID | export-csv C:usersMyUserDocumentsEmptyCollections.csv -noTypeInformation

 Alternatively, if you get the go-ahead to remove these device collections, instead of piping to a select/export-csv statement, you can pipe to remove-wmiobject instead.
For the love of god, run it with -whatif first.  

Thanks for reading, and if you have any questions, feel free to post them in the comments.