Author Posts

May 20, 2014 at 1:25 pm

I have a need for a script that collects computer names and operating systems from a ConfigMgr collection and then groups those computers by operating system. Once it has the OS groupings created, it then needs to pick (at random) a computer name from each of the groups up to a limit of a number of computers specified.

I've figured out the SCCM part and the random part but I'm having a hell of a time wrapping my head around the logic to get this done. Here's an example attempt at explaining it in code:

## This is the total number of computers I need (total) out of all the operating system groups
$NumberOfRandomClientsNeeded = 55

## This outputs objects grouped by operating system containing the computer names in the Group property
$OperatingSystemGroups = Get-WmiObject @ConfigMgrWmiProps -Class "SMS_CM_RES_COLL_$SourceCollectionId" | select Name, DeviceOS | group DeviceOS | sort count -Descending

## This defines only the Top Count operating systems groups in case the number of clients I need is less than the total operating system grouping
## If I have more clients needed than OS groupings, I just use them all
If ($NumberOfRandomClientsNeeded -lt $OperatingSystemGroups) {
  $OperatingSystemGroups = $OperatingSystemGroups[0..($NumberOfRandomClientsNeeded - 1)]
}

## Here's where I'm going to use pseudo-code because I have no idea how to do this
##1. Pick a client from OS group 1.
##2. Pick a client from OS group 2.
##3. Pick a client from OS group 3.
##...
##END OS GROUPS
##XX. Pick a client from OS group 1.
##XX. Pick a client from OS group 2.
##XX. Pick a client from OS group 3.
##...
##END OS GROUPS
##XX. Pick a client from OS group 1.
##XX. Pick a client from OS group 2.
##XX. Pick a client from OS group 3.

I need the code to grab a client from each OS group and repeat through the OS groups until it hits the $NumberOfRandomClientsNeeded number. I do not want it to grab a client from the operating system group back to back. It must iterate through all the OS groups 1 at a time.

I sure hope I'm explaining this well. I started off on this script thinking it'd be easy but I've spent close to 3 hours just trying every kind of nested loop I can think of and I can't get the result I'm looking for.

May 21, 2014 at 2:20 am

Can you add some sample data? I don't have System Center nearby and I am not sure what the result would look like in the $OperatingSystemGroups variable?

If your main issue is how to find the random tem in the array, try using the Get-Random cmdlet. Something like this:

$OperatingSystemGroups | ? { $_.DeviceOS -eq 'osname' } | Get-Random

What this example illustrates is how you can filter they array, pick out the specific items mathing the "osname" and then pass it all to Get-Random to get a randomly selected item from the list.

May 21, 2014 at 3:57 am

In this case, you don't necessarily need a nested loop. You can use the modulus operator to achieve the same result. For example:

$groupCount = 10
$NumberOfRandomClientsNeeded = 55

for ($i = 0; $i -lt $NumberOfRandomClientsNeeded; $i++)
{
    $groupIndex = $i % $groupCount

    Write-Host "Selecting a client from group $groupIndex..."
}

May 21, 2014 at 9:26 am

@dave – That worked great! I had played around with using the modulus operator a little but I never considered getting the group index that way.