MSEndpointMgr

Get Collection Members with a PowerShell GUI

Have you ever thought about copying the system names from a collection to use them for any kind of purpose outside of ConfigMgr 2012? Well, that’s not very easy. You could of course with PowerShell and some smart searches on Google solve the problem. But I wanted to make it even easier, so I created my first PowerShell tool for ConfigMgr 2012. The reason for that was that I needed to migrate some collections with direct membership that was not migrated the proper way.

Overview

  • The Get-CollectionMembersGUI.ps1 script
  • How to use it
  • Error handling

The Get-CollectionMembersGUI.ps1 script

Save the below code to C:\Scripts and give it a name like Get-CollectionMembersGUI.ps1.

#========================================================================
# Created on:   2013-08-29 23:10
# Created by:   Nickolaj Andersen (@NickolajA)
# Version: 1.0.0
#========================================================================
#Functions
function Get-Collections {
    $SiteServer = $TBSiteServer.Text
    $SiteCode = $TBSiteCode.Text
	$CollArray = New-Object System.Collections.ArrayList
	$CollArray = Get-WmiObject -Namespace "root\sms\site_$($SiteCode)" -Class SMS_Collection -ComputerName $SiteServer | Sort-Object -Property Name | Select-Object Name
	$CollArray | ForEach-Object {
    	$CBCollections.Items.Add($_.Name) | Out-Null
	}
	$CBCollections.SelectedIndex = 0
	$Form.Controls.Add($ButtonGetMembers)
	$Form.Controls.Remove($ButtonGetCollections)
}
function Get-CollectionMembers {
    $SiteServer = $TBSiteServer.Text
    $SiteCode = $TBSiteCode.Text
    $CollectionName = $CBCollections.SelectedItem.ToString()
    $Collection = Get-WmiObject -Namespace "root\sms\site_$($SiteCode)" -Class SMS_Collection -ComputerName $SiteServer | Where-Object { $_.Name -like "$($CollectionName)" }
    $CollectionMembers = Get-WmiObject -Namespace "root\sms\site_$($SiteCode)" -ComputerName $SiteServer -Query "SELECT Name FROM SMS_CM_RES_COLL_$($Collection.CollectionID)" | Select-Object Name
    Load-DataGridView -DataGridView $DGVResults -Item $CollectionMembers
	$LabelCount.Text = "Count: $($DGVResults.Rows.Count)"
    $Form.Controls.Add($ButtonReload)
    $Form.Controls.Remove($ButtonGetMembers)
}
function Validate-Data {
    $Error = 0
	$WMIError
    $Global:ErrorProvider = New-Object System.Windows.Forms.ErrorProvider
    $ErrorProvider.Clear()
	$ErrorProvider.BlinkStyle = "NeverBlink"
    if (($TBSiteServer.Text.Length -eq 0) -OR ($TBSiteCode.Text.Length -eq 0)) {
        if ($TBSiteServer.Text.Length -eq 0) {
            $ErrorProvider.SetError($TBSiteServer, "Please enter a site server")
        }
        if ($TBSiteCode.Text.Length -lt 3) {
            $ErrorProvider.SetError($TBSiteCode, "Please enter the site code correct")
        }
    }
    if ($TBSiteServer.Text.Length -gt 1) {
        if (-NOT(Test-Connection $($TBSiteServer.Text) -Count 1 -Quiet)) {
            $ErrorProvider.SetError($TBSiteServer,"Site server not found")
            $Error++
        }
    }
	if (($TBSiteCode.Text.Length -eq 3) -AND ($Error -eq 0)) {
		$GetSiteCode = Get-WmiObject -Namespace "root\sms" -Class "__NAMESPACE" -ComputerName $($TBSiteServer.Text) -ErrorAction Ignore | Select @{Label="Name";Expression={$_.Name.SubString(5)}}
		if (-NOT($GetSiteCode.Name)) {
			$ErrorProvider.SetError($TBSiteCode, "SMS Provider not found on specified site server")
			$Error++
		}
		if (($GetSiteCode.Name) -AND -NOT($GetSiteCode.Name -like $TBSiteCode.Text)) {
			$ErrorProvider.SetError($TBSiteCode, "Wrong site code specified, not matching site code found on site server")
			$Error++
		}
	}
    if (($TBSiteServer.Text.Length -gt 1) -AND ($TBSiteCode.Text.Length -eq 3) -AND ($Error -eq 0)) {
        Get-Collections
		$Form.Controls.Add($ButtonGetMembers)
    }
    else {
        $Form.Controls.Add($ButtonReload)
        $Form.Controls.Remove($ButtonGetCollections)
    }
}
function Load-DataGridView {
	Param(
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		[System.Windows.Forms.DataGridView]$DataGridView,
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		$Item,
	    [Parameter(Mandatory=$false)]
		[string]$DataMember
	)
	$DataGridView.SuspendLayout()
	$DataGridView.DataMember = $DataMember
	if ($Item -IS [System.ComponentModel.IListSource] -OR $Item -IS [System.ComponentModel.IBindingList] -OR $Item -IS [System.ComponentModel.IBindingListView] ) {
		$DataGridView.DataSource = $Item
	}
	else {
		$Array = New-Object System.Collections.ArrayList
		if ($Item -IS [System.Collections.IList]) {
			$Array.AddRange($Item)
		}
		else {
			$Array.Add($Item)
		}
		$DataGridView.DataSource = $Array
	}
	$DataGridView.ResumeLayout()
}
function Clear-Form {
	$DGVResults.DataSource = $null
	$DGVResults.Columns.Clear()
	$DGVResults.Rows.Clear()
	$DGVResults.Refresh()
	$CBCollections.SelectedIndex = -1
	$CBCollections.Items.Clear()
    $TBSiteServer.ResetText()
    $TBSiteCode.ResetText()
	$LabelCount.Text = "Count:"
    $ErrorProvider.Clear()
    $Form.Controls.Add($ButtonGetCollections)
    $Form.Controls.Remove($ButtonReload)
    $Form.Refresh()
}
#Assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#Form
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(660,470)
$Form.MinimumSize = New-Object System.Drawing.Size(660,470)
$Form.MaximumSize = New-Object System.Drawing.Size(660,470)
$Form.SizeGripStyle = "Hide"
$Form.Text = "ConfigMgr Collection Members 1.0.0"
#Text
$LabelCount = New-Object System.Windows.Forms.Label
$LabelCount.Location = New-Object System.Drawing.Size(520,85)
$LabelCount.Size = New-Object System.Drawing.Size(170,50)
$LabelCount.Text = "Count:"
$Form.Controls.Add($LabelCount)
$TBSiteServer = New-Object System.Windows.Forms.TextBox
$TBSiteServer.Location = New-Object System.Drawing.Size(20,40)
$TBSiteServer.Size = New-Object System.Drawing.Size(170,50)
$TBSiteServer.TabIndex = "1"
$Form.Controls.Add($TBSiteServer)
$TBSiteCode = New-Object System.Windows.Forms.TextBox
$TBSiteCode.Location = New-Object System.Drawing.Size(230,40)
$TBSiteCode.Size = New-Object System.Drawing.Size(170,50)
$TBSiteCode.TabIndex = "2"
$Form.Controls.Add($TBSiteCode)
#ComboBoxes
$CBCollections = New-Object System.Windows.Forms.ComboBox
$CBCollections.Location = New-Object System.Drawing.Size(440,40)
$CBCollections.Size = New-Object System.Drawing.Size(170,50)
$CBCollections.DropDownHeight = 200
$CBCollections.DropDownWidth = 200
$CBCollections.TabIndex = "4"
$Form.Controls.Add($CBCollections)
#DataGridView
$DGVResults = New-Object "System.Windows.Forms.DataGridView"
$DGVResults.AllowUserToAddRows = $False
$DGVResults.AllowUserToDeleteRows = $False
$DGVResults.ColumnHeadersHeightSizeMode = "DisableResizing"
$DGVResults.AutoSizeColumnsMode = "Fill"
$DGVResults.RowHeadersWidthSizeMode = "DisableResizing"
$DGVResults.Anchor = "Top, Bottom, Left, Right"
$DGVResults.Location = "20, 100"
$DGVResults.Name = "datagridviewResults"
$DGVResults.ReadOnly = $True
$DGVResults.Size = "470, 290"
$DGVResults.BackGroundColor = "White"
$DGVResults.TabIndex = "5"
$Form.Controls.Add($DGVResults)
#Groupboxes
$GBCollectionName = New-Object System.Windows.Forms.GroupBox
$GBCollectionName.Location = New-Object System.Drawing.Size(430,20)
$GBCollectionName.Size = New-Object System.Drawing.Size(200,50)
$GBCollectionName.Text = "Collection name:"
$Form.Controls.Add($GBCollectionName)
$GBSiteServer = New-Object System.Windows.Forms.GroupBox
$GBSiteServer.Location = New-Object System.Drawing.Size(10,20)
$GBSiteServer.Size = New-Object System.Drawing.Size(200,50)
$GBSiteServer.Text = "Site server:"
$Form.Controls.Add($GBSiteServer)
$GBSiteCode = New-Object System.Windows.Forms.GroupBox
$GBSiteCode.Location = New-Object System.Drawing.Size(220,20)
$GBSiteCode.Size = New-Object System.Drawing.Size(200,50)
$GBSiteCode.Text = "Site code:"
$Form.Controls.Add($GBSiteCode)
$GBMembers = New-Object System.Windows.Forms.GroupBox
$GBMembers.Location = New-Object System.Drawing.Size(10,80)
$GBMembers.Size = New-Object System.Drawing.Size(490,320)
$GBMembers.Text = "Collection members:"
$Form.Controls.Add($GBMembers)
#Links
$OpenLink = {[System.Diagnostics.Process]::Start("https://msendpointmgr.com")}
$BlogLink = New-Object System.Windows.Forms.LinkLabel
$BlogLink.Location = New-Object System.Drawing.Size(10,407)
$BlogLink.Size = New-Object System.Drawing.Size(150,25)
$BlogLink.Text = "www.scconfigmgr.com"
$BlogLink.Add_Click($OpenLink)
$Form.Controls.Add($BlogLink)
#Buttons
$ButtonGetCollections = New-Object System.Windows.Forms.Button
$ButtonGetCollections.Location = New-Object System.Drawing.Size(515,320)
$ButtonGetCollections.Size = New-Object System.Drawing.Size(110,80)
$ButtonGetCollections.Text = "Get collections"
$ButtonGetCollections.TabIndex = "3"
$ButtonGetCollections.Add_Click({Validate-Data})
$Form.Controls.Add($ButtonGetCollections)
$ButtonGetMembers = New-Object System.Windows.Forms.Button
$ButtonGetMembers.Location = New-Object System.Drawing.Size(515,320)
$ButtonGetMembers.Size = New-Object System.Drawing.Size(110,80)
$ButtonGetMembers.Text = "Get members"
$ButtonGetMembers.TabIndex = "3"
$ButtonGetMembers.Add_Click({Get-CollectionMembers})
$ButtonReload = New-Object System.Windows.Forms.Button
$ButtonReload.Location = New-Object System.Drawing.Size(515,320)
$ButtonReload.Size = New-Object System.Drawing.Size(110,80)
$ButtonReload.Text = "Reload"
$ButtonReload.TabIndex = "3"
$ButtonReload.Add_Click({Clear-Form})
#Create the form
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()

How to use it

1. Open an elevated PowerShell command prompt.
2. Browse to C:\Scripts (or the location that you chose to save the script).
3. Run the following command:

.\Get-CollectionMembersGUI.ps1

4. The program will now launch and it should look like this:
45_1
5. Enter your Primary Site server computer name in the Site server text field.
6. Enter the site code of your Primary Site server in the Site code text field.
7. Click on Get collections.
8. The Collection name drop down box should now be populated will all available collections on the specified site server. Choose the collection you’d like to get the members for.
9. Click on Get members.
10. In the Collection members datagrid view, all members in the choosen collection should now be displayed. It’s now possible to select all system and copy their name.
11. To reload the program and start over, click on the Reload button.
45_2

Error handling

In order for the program to handle some human errors, I’ve added a few error handling capabilities:

  • Site server text field, a Test-Connection will be performed in order to  see if the entered site server computer name is able to be resolved with DNS and if it’s online. Atleast one character will have to be entered for it to work.
  • Site code text field, the entered site code will be checked if there’s a site_<site_code> namespace available on the entered site server. The text field needs to have atleast 3 characters to work.

45_3
45_4
Unfortunately there’s no error handling if you’ve entered a site code with more than 3 characters. The script will only show the Reload button, and you’d have to start over. That might be a feature that will be added in the future.

Nickolaj Andersen

Chief Technical Architect and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences such as Microsoft Ignite, NIC Conference and IT/Dev Connections including nordic user groups.

1 comment

  • I know this is an old thread, but what if I wanted to get the collections that a device is a member of-can you suggest any modifications for that?

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.