Powershell Forms - пауза с кнопкой - PullRequest
0 голосов
/ 23 января 2019

У меня есть скрипт на основе форм, который делает много копий файлов из разных источников.Основной цикл копирования файлов может продолжаться долго, и я хотел бы добавить кнопку паузы для приостановки обработки (пока кнопка паузы не будет нажата снова)

Следуя совету здесь , Я использую [System.Windows.Forms.Application]::DoEvents(), чтобы сохранить отзывчивость формы и предоставить способ корректно разорвать цикл копирования.

Я изо всех сил пытаюсь понять, как я могу ввести кнопку для приостановки "Цикл ForEach "вместо того, чтобы его нарушать - кто-нибудь может направить меня в правильном направлении, так как мои попытки использовать Do-Before / While, похоже, каким-то образом приводят к зависанию сценария?

Чрезвычайно упрощенный пример того, что яделать это ниже:

$StartCopyButton.Add_Click({
    $script:CancelLoop = $false
    $script:PauseToggle = $false
    $CancelButton.Enabled = $true
    $StartCopyButton.Enabled = $false

    Get-ChildItem -LiteralPath $Source -Recurse -File | ForEach {
        Copy-Item -Path $.FullName -Destination $NewDestination
        [System.Windows.Forms.Application]::DoEvents()
        If($script:CancelLoop -eq $true) {
            #Exit the loop
            Break;
        }
        If ($script:PauseToggle) {
            Do { 
            [System.Windows.Forms.Application]::DoEvents()
            } Until (!$script:PauseToggle)
        }
    }
    $CancelButton.Enabled = $false
    $StartCopyButton.Enabled = $true
})

$CancelButton.Add_Click({
    $script:CancelLoop = $true
})
$PauseButton.Add_Click({
    # Boolean change value to true/false
    $script:PauseToggle = !$script:PauseToggle
})

Ответы [ 2 ]

0 голосов
/ 23 января 2019

На самом деле, вам нужна только одна кнопка для запуска и приостановки. Вот один очень простой подход, чтобы проиллюстрировать мою идею, НЕ ПРОВЕРЕНО:

$script:CancelLoop = $false
$script:PauseLoop = $false
$CopyButton.Add_Click({
    # toggle the start/pause state when clicked
    $script:PauseLoop = -not $script:PauseLoop
    if ($script:PauseLoop) {
        $CancelButton.Enabled = $false
        $CopyButton.Text = "Start"
    }
    else {
        $CancelButton.Enabled = $true
        $CopyButton.Text = "Pause"
        # start / resume the loop
        Get-ChildItem $Source -Recurse -File | foreach {
            $newPath = Join-Path $NewDestination $_.Name
            # test if file was already copied
            # (might want to compare modified times too)
            if (-not (Test-Path $newPath)) {
                Copy-Item $_.FullName $newPath
            }
            [System.Windows.Forms.Application]::DoEvents()
            if ($script:CancelLoop -or $script:PauseLoop) {
                # exit loop if cancelled or paused
                break
            }
        }
        $CancelButton.Enabled = $false
        $CopyButton.Text = "Start"
    }
})

Другой подход - сначала получить все файлы, сохранить их в коллекции, а затем сохранить индекс и приостановить / возобновить на этом этапе. Но это несет в себе риск того, что список файлов может измениться за это время. Так что действительно «безопасное» решение было бы более сложным.

0 голосов
/ 23 января 2019

Вы можете проверить состояние паузы и, если оно истинно, сделать пустой цикл с DoEvents. Вот так (хотя не проверял):

$StartCopyButton.Add_Click({
    $script:CancelLoop = $false
    $script:Pause = $false
    $CancelButton.Enabled = $true
    $StartCopyButton.Enabled = $false

    Get-ChildItem -LiteralPath $Source -Recurse -File | ForEach {
        Copy-Item -Path $.FullName -Destination $NewDestination
        [System.Windows.Forms.Application]::DoEvents()
        while ($script:Pause -and !$script:CancelLoop) {
            [System.Windows.Forms.Application]::DoEvents()
            sleep 0.1
        }
        If($script:CancelLoop -eq $true) {
            #Exit the loop
            Break;
        }
    }
    $CancelButton.Enabled = $false
    $StartCopyButton.Enabled = $true
})

$CancelButton.Add_Click({
    $script:CancelLoop = $true
})
$PauseButton.Add_Click({
    $script:Pause = !$script:Pause
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...