PowerShell Active Directory Group Picker

This post provides an example of a PowerShell Active Directory Group Picker. You can also find a similar example of our PowerShell Active Directory People Picker.

When using one of my PowerShell GUI tools, we needed to select a valid Active Directory group. I use the word ‘valid’ because merely prompting the user to enter free text created too much margin for error, so I needed to return a group that definitely existed.

There are ways to do this via PowerShell using the Remote Server Administration Tools (RSAT), but I don’t like my scripts relying on external tools and I like them to remain portable, whilst keeping the host machine clean.

Ultimately I ended up interfacing with Active Directory using PowerShell and ADSI. The script basically invokes a function that launches a Windows Form. It has a textbox to search for a group, and a ListBox to display them. It then sets a variable in the script’s context with the selected group, which is accessible from the initial call.

Add-Type -AssemblyName PresentationCore,PresentationFramework
function Select-ADObject
$form = New-Object System.Windows.Forms.Form
$form.Text = "Active Directory Search"
$form.Size = New-Object System.Drawing.Size(340,320)
$form.StartPosition = "CenterScreen"
$SearchButton = New-Object System.Windows.Forms.Button
$SearchButton.Location = New-Object System.Drawing.Point(260,10)
$SearchButton.Size = New-Object System.Drawing.Size(50,23)
$SearchButton.Cursor = [System.Windows.Forms.Cursors]::Hand
$SearchButton.Text = 'Search'
$SearchButton.Enabled = $false
$CancelButton.Enabled = $false
#start progress bar
$ProgressBar.MarqueeAnimationSpeed = 10;
$searchVal = $SearchText.Text
$job = Start-Job -ArgumentList $searchVal -ScriptBlock  {
if ($searchVal -ne $null -and $searchVal -ne "") {
$objSearcher.SizeLimit = 30
$colProplist = "name"
foreach ($i in $colPropList) { $objSearcher.PropertiesToLoad.Add($i) | out-null } 
$colResults = $objSearcher.FindAll()
return $colResults
while($job.State -eq 'Running') {
$results = $job | Receive-Job -AutoRemoveJob -Wait
if ($results -eq $null -or $results.Count -eq 0) {
$SearchButton.Enabled = $true
$CancelButton.Enabled = $true
#needed to reset marquee to 0
$ProgressBar.MarqueeAnimationSpeed = 0;
$ProgressBar.Value = 0;
$SelectButton.Enabled = $false
[System.Windows.MessageBox]::Show("Search returned no results.")
foreach ($objResult in $results)
[void] $ListBox.Items.Add(($objResult.Properties).name[0])	
$SearchButton.Enabled = $true
$CancelButton.Enabled = $true
#needed to reset marquee to 0
$ProgressBar.MarqueeAnimationSpeed = 0;
$ProgressBar.Value = 0;
$SearchText = New-Object System.Windows.Forms.TextBox
$SearchText.Location = New-Object System.Drawing.Point(10,11)
$SearchText.Size = New-Object System.Drawing.Size(245,20)
$SearchText.Multiline = $false   
$SearchText.AcceptsReturn = $true 
if ($_.KeyCode -eq [System.Windows.Forms.Keys]::Enter) {
$SelectButton = New-Object System.Windows.Forms.Button
$SelectButton.Location = New-Object System.Drawing.Point(205,245)
$SelectButton.Size = New-Object System.Drawing.Size(50,23)
$SelectButton.Text = "Select"
$SelectButton.Cursor = [System.Windows.Forms.Cursors]::Hand
if ($ListBox.SelectedItems.Count -eq 0) {
[System.Windows.MessageBox]::Show("No item selected.")
$script:selectedADGroup = $ListBox.SelectedItem; 
write-host $ListBox.SelectedText; 
$SelectButton.Enabled = $false
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(260,245)
$CancelButton.Size = New-Object System.Drawing.Size(50,23)
$CancelButton.Text = "Cancel"
$CancelButton.Cursor = [System.Windows.Forms.Cursors]::Hand
$CancelButton.Add_Click({ $script:selectedADGroup = $null; $form.Close()})
$ListBox = New-Object System.Windows.Forms.ListBox
$ListBox.Location = New-Object System.Drawing.Point(10,40)
$ListBox.Size = New-Object System.Drawing.Size(300, 20)
$ListBox.Height = 200
if ($ListBox.SelectedItems.Count -eq 1) {
$SelectButton.Enabled = $true
$ProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProgressBar.Location = New-Object System.Drawing.Point(10, 246)
$ProgressBar.Size = New-Object System.Drawing.Size(190, 21)
$ProgressBar.Value = 0
$ProgressBar.MarqueeAnimationSpeed = 0;
$form.TopMost = $true
$form.Add_Shown({$form.Activate(); $SearchText.focus()})
[void] $form.ShowDialog()
return $script:selectedADGroup
$selectedObject = Select-ADObject
write-host $selectedObject