1

I'm using the following code to create a listbox and using it to reboot a computer based on the Display name in the listbox. I actually want to replace the display name with the actual computer name. Can I use an array for that? I'm still getting used to powershell. If I can't do an array, is there a property or collection in the listbox that I can store the computer name in?

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please select a computer:'
$form.Controls.Add($label)

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

[void] $listBox.Items.Add('Screen in building 1 first floor')
[void] $listBox.Items.Add('Screen in building 1 second floor')
[void] $listBox.Items.Add('Screen in building 2 4th floor')
[void] $listBox.Items.Add('Screen in building 3 basement')

$form.Controls.Add($listBox)

$form.Topmost = $true

$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $c = Get-Credential Domain\Username
    Restart-Computer -ComputerName "Variable 2 of selection from listbox" -Credential $c -Force
    $x = $listBox.SelectedItem
    $x
}
0

2 Answers 2

1

Updated: In the example below I am going to use computers from Active Directory using Import-Module ActiveDirectory

In order to add items to your listbox with a multidimensional array, we can utilize an Object and the NoteProperty to add to the listbox

Ex:

#This example I am grabbing all computers from AD with the OS of windows server -- all windows servers
Import-Module ActiveDirectory
#Using the Name property for reboot and the Description for the listbox... you can use a different attribute if you like
$Computers = Get-ADComputer -filter {OperatingSystem -like "Windows Server*" -and Enabled -eq $true} -Properties Name, Description, OperatingSystem  | Select Name, Description, OperatingSystem

$listboxCollection =@()

foreach($Computer in $Computers)
{

    $Object = New-Object Object 
    $Object | Add-Member -type NoteProperty -Name CompName -Value $Computer.Name
    $Object | Add-Member -type NoteProperty -Name Values -Value $Computer.Description
    #fill the $listboxCollection
    $listboxCollection += $Object
}

#Add collection to the $listbox
$listBox.Items.AddRange($listboxCollection)

If you were to display your form from here, all your entries would show as System.Object. To get the Decription from each collection in the $listboxCollection to show we have tell it the ValueMember and DisplayMember.

Ex:

#This is using the properties above to display the correct item
$listBox.ValueMember = "CompName"
$listBox.DisplayMember = "Values"

Keeping with your original post, to get the selected item of the listbox on the OK button, you will need to put in a condition. However, there are several different ways to handle this event.

Ex:

#show form as dialog
$result = $form.ShowDialog()

if($result = [System.Windows.Forms.DialogResult]::OK)
{
    $selectedComputer = $listBox.SelectedItem.CompName  
    Restart-Computer -ComputerName $selectedComputer -Credential Get-Credential Domain\Username -Force
}

The variable $selectedComputer will be the selected computer. Note: In this example there is nothing checking to make sure there is a valid selection.

Complete Solution:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing


#This example I am grabbing all computers from AD with the OS of windows server -- all windows servers
Import-Module ActiveDirectory
#Using the Name property for reboot and the Description for the listbox... you can use a different attribute if you like
$Computers = Get-ADComputer -filter {OperatingSystem -like "Windows Server*" -and Enabled -eq $true} -Properties Name, Description, OperatingSystem  | Select Name, Description, OperatingSystem

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

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

#create an empty collection to use later
$listboxCollection =@()

foreach($Computer in $Computers)
{

    $Object = New-Object Object 
    $Object | Add-Member -type NoteProperty -Name CompName -Value $Computer.Name
    $Object | Add-Member -type NoteProperty -Name Values -Value $Computer.Description
    $listboxCollection += $Object
}

$listBox.Items.AddRange($listboxCollection)

#This is using the properties above to display the correct item
$listBox.ValueMember = "CompName"
$listBox.DisplayMember = "Values"


#add listbox to form
$form.Controls.Add($listBox)

#Ok Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

#keep on top
$form.Topmost = $true

#show form as dialog
$result = $form.ShowDialog()

if($result = [System.Windows.Forms.DialogResult]::OK)
{
    #this tells it to get the Name of the property and not just the Item
    $selectedComputer = $listBox.SelectedItem.CompName    
    Restart-Computer -ComputerName $selectedComputer -Credential Get-Credential Domain\Username -Force
}

Note: if you use the Active Directory query your computers must all have a Name and Description attribute (unless of course you plan on handling empty/null values)

Sign up to request clarification or add additional context in comments.

3 Comments

Good info but I might be missing something. I might need a multidimensional array or a hash table. I want to use a description to show in the Listbox but the actual computer to be rebooted to not show and only be in code. Thanks for your input.
@MattWilliamson updated to include using a multidimensional array. Please update the title of your original question to include this. It might help someone else in the future.
@MattWilliamson Is the update what you are trying to accomplish?
1

This is actually pretty simple with powershell objects. Make an array of computer objects that define any properties (you can do this automatically). Add them to the listbox and select the item you want to display. Later, you can access the other property as well (SelectedItem.Name in this case).

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$x = @()
$x += [pscustomobject]@{Name="cname"; Display="Friendly Name"}
$x += [pscustomobject]@{Name="cname2"; Display="Friendly Name2"}
$x += [pscustomobject]@{Name="cname3"; Display="Friendly Name3"}

$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10,40)
$listBox.Size = New-Object System.Drawing.Size(260,20)
$listBox.Height = 80
$listBox.Items.AddRange($x)
$listBox.DisplayMember = "Display"
$form.Controls.Add($listBox)

$labelDN = New-Object system.windows.Forms.Label
$labelDN.AutoSize = $true
$labelDN.Width = 25
$labelDN.Height = 10
$labelDN.location = new-object system.drawing.point(1,1)
$labelDN.Font = "Microsoft Sans Serif,10"
$labelDN.Text = "Hello"
$Form.controls.Add($labelDN)

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.Add_Click({
 $labelDN.Text = $listBox.SelectedItem.Name
})
$form.Controls.Add($OKButton)


$form.ShowDialog()

You can actually add all your code in the Add_Click method if you would like to slim things down for yourself. With your solution it was a bit hard to test since it closes the application with every selection. Of course, you could implement this however you want.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.