首页 > 解决方案 > GUI-button to exit loop, Move-Item Job

问题描述

I'm struggling to break the while loop when the "Off" button is being pressed. Instead, after starting the moving process, I am running into an endless loop.

$objForm.Controls.Add($StartButton)
$objForm.Controls.Add($OffButton)

$OffButton = New-Object System.Windows.Forms.Button
$OffButton.Location = New-Object System.Drawing.Size(340,105)
$OffButton.Size = New-Object System.Drawing.Size(90,28)
$OffButton.Text = 'Off'
$OffButton.Name = 'Off'
$OffButton.Font = [System.Drawing.Font]::New("Microsoft Sans Serif", 11)
$OffButton.Add_Click({$script:AktiveLoop = $False})
$objForm.Controls.Add($OffButton)

$StartButton = New-Object System.Windows.Forms.Button
$StartButton.Location = New-Object System.Drawing.Size(340,135)
$StartButton.Size = New-Object System.Drawing.Size(90,28)
$StartButton.Text = 'Start'
$StartButton.Name = 'Start'
$StartButton.Font = [System.Drawing.Font]::New("Microsoft Sans Serif", 11)
$StartButton.Add_Click({
    $script:AktiveLoop = $true

    while ($script:AktiveLoop -eq $true) {
        Move-Item $source -Destination $destination
        Start-Sleep -Seconds 1.0

        if ($script:AktiveLoop = $False) {
            break
        }
    }
})
[void] $objForm.ShowDialog()

标签: powershellloopsuser-interfacebuttonbreak

解决方案


Although there is discussion about using DoEvents, the fact that your button 'Off' click does not seem to be fired has to do with the Start-Sleep you are putting in the loop.

Start-Sleep makes the form unresponsive. If you use [System.Windows.Forms.Application]::DoEvents() instead the button click events are processed.

Also, from a user point of view, it is best to disable the 'Off 'button when the form is first drawn and toggle the enabled startus of both buttons inside te Click events.

For this I have made some changes to the code given in the example:

Add-Type -AssemblyName System.Windows.Forms

$objForm   = New-Object System.Windows.Forms.Form

$OffButton = New-Object System.Windows.Forms.Button
$OffButton.Location = New-Object System.Drawing.Size(340,105)
$OffButton.Size = New-Object System.Drawing.Size(90,28)
$OffButton.Text = 'Off'
$OffButton.Name = 'Off'
$OffButton.Font = [System.Drawing.Font]::New("Microsoft Sans Serif", 11)
# initially disable the 'Off' button
$OffButton.Enabled   = $false
$OffButton.Add_Click({
    $script:AktiveLoop   = $false
    $OffButton.Enabled   = $false
    $StartButton.Enabled = $true

})
$objForm.Controls.Add($OffButton)

$StartButton = New-Object System.Windows.Forms.Button
$StartButton.Location = New-Object System.Drawing.Size(340,135)
$StartButton.Size = New-Object System.Drawing.Size(90,28)
$StartButton.Text = 'Start'
$StartButton.Name = 'Start'
$StartButton.Font = [System.Drawing.Font]::New("Microsoft Sans Serif", 11)
# initially enable the 'Off' button
$StartButton.Enabled = $true
$StartButton.Add_Click({
    # switch the buttons Enabled status so the user can not click the same button twice
    $OffButton.Enabled   = $true
    $StartButton.Enabled = $false
    $script:AktiveLoop   = $true

    while ($script:AktiveLoop) {
        # perform some action here. (added -WhatIf here for testing)
        Move-Item $source -Destination $destination -WhatIf

        # Start-Sleep makes the form unresponsive, so don't use that.

        # DoEvents() suspends the current thread and processes 
        # window messages like a click on the 'Off' button.
        [System.Windows.Forms.Application]::DoEvents()
    }
})
$objForm.Controls.Add($StartButton)


[void] $objForm.ShowDialog()
$objForm.Dispose()

p.s. You added the buttons to the form even before you have defined them, so I removed that.

Hope this helps


推荐阅读