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:
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.
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.
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.
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?