Selecting items from a list box.

Tagged: 

This topic contains 6 replies, has 4 voices, and was last updated by Profile photo of Jon Scriven Jon Scriven 2 years, 7 months ago.

  • Author
    Posts
  • #11593
    Profile photo of Nick Shemonsky
    Nick Shemonsky
    Participant

    Hey all. I'm working on a list box to choose a user from a provided list, in this case users having the last name of Smith for an example. I've referenced the technet article on creating a list box, and while it populates correctly the variable I'm storing the selected user in returns nothing. I'm assuming this is probably due to how I'm passing each user's sam account name to the list box but I'm not certain.

    If anyone code provide some insight, I'd appreciate it. Code below.


    $search_properties = "sAMAccountName", "sn"
    $search = "OU=Test,DC=contoso,DC=com"
    $lastname = "Smith"
    $users = Get-ADUser -Filter * -SearchBase $search -Properties $search_properties |
    Select-Object @{Name="sAM";Expression={$_.sAMAccountName}},
    @{Name="Last Name";Expression={$_.sn}} |
    Where {$_."Last Name" -eq $lastname}

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Select the user to remove"
    $objForm.Size = New-Object System.Drawing.Size(300,200)
    $objForm.StartPosition = "CenterScreen"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$selection=$objListBox.SelectedItem;$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75,120)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$selection=$objListBox.SelectedItem;$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150,120)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(280,20)
    $objLabel.Text = "Please select a user:"
    $objForm.Controls.Add($objLabel)

    $objListBox = New-Object System.Windows.Forms.ListBox
    $objListBox.Location = New-Object System.Drawing.Size(10,40)
    $objListBox.Size = New-Object System.Drawing.Size(260,20)
    $objListBox.Height = 80
    $objListBox.Sorted = $True

    Foreach ($user in $users) {
    [void] $objListBox.Items.Add($user."sAM")
    }

    $objForm.Controls.Add($objListBox)

    $objForm.Topmost = $True

    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()

    $selection

  • #11607
    Profile photo of Nick Shemonsky
    Nick Shemonsky
    Participant

    That makes perfect sense. Thanks!

  • #19067
    Profile photo of Jon Scriven
    Jon Scriven
    Participant

    Thanks for this fix. I had problems with the same code too and was so glad to find this excellent fix!

  • #19071
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    No problem! Just a heads-up, these fixes have been published to TechNet and via a "Hey, Scripting Guy!" article last month: http://blogs.technet.com/b/heyscriptingguy/archive/2014/08/02/weekend-scripter-fixing-powershell-gui-examples.aspx

  • #19072
    Profile photo of Jon Scriven
    Jon Scriven
    Participant

    Thanks. Shame they don't have a link to that article in the original which would have saved me several hours of tearing my hair out earlier!

    Much appreciate your help.

    Jon

  • #11601
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I don't know what the deal is with those sample articles on TechNet. This is the second one I've seen where they used the approach of trying to set a variable's value from inside the OK Button's Click event. This doesn't work, as written, due to variable scoping issues. You're just setting a variable named $selection inside that script block.

    The quick and dirty fix for this is to use the script: scope modifier when assigning the variable:

    $script:selection = $objListBox.SelectedItem
    

    I don't actually like this method much, but it does work.

    Here's how I would modify their sample code. (I would have modified yours instead, but copying and pasting it out of the forum post stuck everything on one giant line for some reason.)

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
    
    $objForm = New-Object System.Windows.Forms.Form 
    $objForm.Text = "Select a Computer"
    $objForm.Size = New-Object System.Drawing.Size(300,200) 
    $objForm.StartPosition = "CenterScreen"
    
    # Got rid of the block of code related to KeyPreview and KeyDown events.
    
    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75,120)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    
    # Got rid of the Click event for the OK button, and instead just assigned its DialogResult property to OK.
    $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    
    $objForm.Controls.Add($OKButton)
    
    # Setting the form's AcceptButton property causes it to automatically intercept the Enter keystroke and
    # treat it as clicking the OK button (without having to write your own KeyDown events).
    $objForm.AcceptButton = $OKButton
    
    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150,120)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    
    # Got rid of the Click event for the Cancel button, and instead just assigned its DialogResult property to Cancel.
    $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    
    $objForm.Controls.Add($CancelButton)
    
    # Setting the form's CancelButton property causes it to automatically intercept the Escape keystroke and
    # treat it as clicking the OK button (without having to write your own KeyDown events).
    $objForm.CancelButton = $CancelButton
    
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20) 
    $objLabel.Size = New-Object System.Drawing.Size(280,20) 
    $objLabel.Text = "Please select a computer:"
    $objForm.Controls.Add($objLabel) 
    
    $objListBox = New-Object System.Windows.Forms.ListBox 
    $objListBox.Location = New-Object System.Drawing.Size(10,40) 
    $objListBox.Size = New-Object System.Drawing.Size(260,20) 
    $objListBox.Height = 80
    
    [void] $objListBox.Items.Add("atl-dc-001")
    [void] $objListBox.Items.Add("atl-dc-002")
    [void] $objListBox.Items.Add("atl-dc-003")
    [void] $objListBox.Items.Add("atl-dc-004")
    [void] $objListBox.Items.Add("atl-dc-005")
    [void] $objListBox.Items.Add("atl-dc-006")
    [void] $objListBox.Items.Add("atl-dc-007")
    
    $objForm.Controls.Add($objListBox) 
    
    $objForm.Topmost = $True
    
    # Now, instead of having events in the form assign a value to a variable outside of their scope, the code that calls the dialog
    # instead checks to see if the user pressed OK and selected something from the box, then grabs that value.
    
    $result = $objForm.ShowDialog()
    if ($result -eq [System.Windows.Forms.DialogResult]::OK -and $objListBox.SelectedIndex -ge 0)
    {
        $selection = $objListBox.SelectedItem
        $selection
    
        # Do something with $selection
    }
    
  • #16989
    Profile photo of Gary Burke
    Gary Burke
    Participant

    Hi Dave,

    Your previous answer helped me out too. Would you mind reworking this one as well? It seems to have a similar problem.

    http://technet.microsoft.com/en-us/library/ff730941.aspx

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Data Entry Form"
    $objForm.Size = New-Object System.Drawing.Size(300,200)
    $objForm.StartPosition = "CenterScreen"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objTextBox.Text;$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(75,120)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(150,120)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(280,20)
    $objLabel.Text = "Please enter the information in the space below:"
    $objForm.Controls.Add($objLabel)

    $objTextBox = New-Object System.Windows.Forms.TextBox
    $objTextBox.Location = New-Object System.Drawing.Size(10,40)
    $objTextBox.Size = New-Object System.Drawing.Size(260,20)
    $objForm.Controls.Add($objTextBox)

    $objForm.Topmost = $True

    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()

    $x

You must be logged in to reply to this topic.