Home > Blockchain >  PowerShell GUI - Move Item (Line) from One Textbox to another
PowerShell GUI - Move Item (Line) from One Textbox to another

Time:08-13

I hope someone can help me understand what I am doing wrong. The script works, if I enter multiple computers or multiple lines, but if I only enter 1 line (1 value). Lets say: Computer 201... the result will be 1

I have disabled the PING feature for now until I can figure out why it does not work with 1 line. I added the whole code so you can test it yourself.
Thank you

# Load required assemblies
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

# Drawing form and controls
$Harvester = New-Object System.Windows.Forms.Form
    $Harvester.Text = "Ping Computers"
    $Harvester.Size = New-Object System.Drawing.Size(490,300)
    $Harvester.FormBorderStyle = "FixedDialog"
    $Harvester.TopMost = $true
    $Harvester.MaximizeBox = $false
    $Harvester.MinimizeBox = $false
    $Harvester.ControlBox = $true
    $Harvester.StartPosition = "CenterScreen"
    $Harvester.Font = "Segoe UI"


#======================== INPUTBOX - Computers ========================#
$label_message2 = New-Object System.Windows.Forms.Label
    $label_message2.Location = New-Object System.Drawing.Size(20,10)
    $label_message2.Size = New-Object System.Drawing.Size(100,15)
    $label_message2.Text = "Computers"
    $Harvester.Controls.Add($label_message2)    
    
# Inputbox    
    $Inputbox = New-Object System.Windows.Forms.TextBox
    $Inputbox.Multiline = $True;
    $Inputbox.Location = New-Object System.Drawing.Size(20,30)
    $Inputbox.Size = New-Object System.Drawing.Size(200,150)
    $Inputbox.ScrollBars = "Vertical"
    $Harvester.Controls.Add($Inputbox)


#======================== INPUTBOX - Completed ========================#
$label_message_success = New-Object System.Windows.Forms.Label
    $label_message_success.Location = New-Object System.Drawing.Size(250,10)
    $label_message_success.Size = New-Object System.Drawing.Size(100,15)
    $label_message_success.Text = "Successful"
    $Harvester.Controls.Add($label_message_success)    
    
# Inputbox    
    $Inputbox_success = New-Object System.Windows.Forms.TextBox
    $Inputbox_success.Multiline = $True;
    $Inputbox_success.Location = New-Object System.Drawing.Size(250,30)
    $Inputbox_success.Size = New-Object System.Drawing.Size(200,150)
    $Inputbox_success.ScrollBars = "Vertical"
    $Harvester.Controls.Add($Inputbox_success)



#======================== Ping ========================#   
$button_Ping = New-Object System.Windows.Forms.Button
    $button_Ping.Location = New-Object System.Drawing.Size(120,200)
    $button_Ping.Size = New-Object System.Drawing.Size(80,32)
    $button_Ping.TextAlign = "MiddleCenter"
    $button_Ping.Text = "Ping"
    $button_Ping.Add_Click({
       
        If ($Inputbox.TextLength -eq 0){
            Add-Type -AssemblyName System.Windows.Forms
            [System.Windows.Forms.MessageBox]::Show('Please enter at 1 computer to perform this action')
            Return
        }
    
        
        [collections.arraylist] $ref = @(($Inputbox.Text -split '\r?\n').Trim() -ne '')
        if(-not $ref) { return } # if the textbox is empty, don't do anything

        $i = 0
        1..$ref.Count | ForEach-Object {
            #if(Test-Connection $ref[$i] -Quiet) {
                $Inputbox_success.Text  = $ref[$i]   [environment]::NewLine
                $ref.RemoveAt($i)
            #}
            
            $Inputbox.Text = $ref | Out-String
            $Inputbox, $Inputbox_success | ForEach-Object Refresh
        }

    })
$Harvester.Controls.Add($button_Ping)



# show form
$Harvester.Add_Shown({$Harvester.Activate()})
[void] $Harvester.ShowDialog()

CodePudding user response:

On a single object you get a value of 1 because of this line:

[collections.arraylist] $ref = @(($Inputbox.Text -split '\r?\n').Trim() -ne '')

More specifically because when a string is evaluated against -ne '' it will return $true or $false, but when you pass an array to that it will instead output all results where that evaluated as true. The way to fix this is to force it to be an array every time. That can be done like this:

[collections.arraylist] $ref = [string[]]($Inputbox.Text -split '\r?\n') -ne ''

That fixes that, but it still leaves other issues, or, at least one other issue I see. You set $i to 0, then loop through things starting at 1, but always reference $i, which will always evaluate to 0, and effectively manipulate item 0 in the $ref array for each thing you evaluate against. So if your If statement succeeds on 3 out of 6 things it will always move the first 3 things over, regardless of what succeeds. To resolve that I changed your code as little as I could, but ended up with this:

    0..($ref.Count -1) | ForEach-Object {
        # if(Test-Connection $ref[$i] -Quiet) {
        if($ref[$_][-1]%2){
            $Inputbox_success.Text  = $ref[$_]   [environment]::NewLine
        }
        
    }
    $Inputbox.Text = $ref |Where{$Inputbox_success.Text -notmatch ([regex]::Escape($_))}| Out-String
    $Inputbox, $Inputbox_success | ForEach-Object Refresh

So rather than remove things from the array, I rather copy the successes to the $Inputbox_success box, and then rebuild $Inputbox based on the items that are not present in $Inputbox_success at the end. Now, I just set $Inputbox.text to be this:

$Inputbox.Text = @'
Computer201
Computer202
Computer203
Computer204
Computer206
Computer207
'@

And evaluated which name ended in an odd number, but you can comment out my If statement, and re-implement your own to make it actually ping things and go off that.

  • Related