我有一个基于表单的脚本,可以从各种来源执行大量的文件副本。复制文件的主循环可以运行很长时间,我想添加一个暂停按钮来保持处理(直到再次按下暂停按钮)
遵循here的建议,我使用[System.Windows.Forms.Application]::DoEvents()
来保持表单响应,并提供一种方法,如果需要优雅地打破复制循环。
我很难看到如何引入一个按钮来暂停“ForEach”循环而不是打破它 - 任何人都可以指出我正确的方向,因为我尝试使用Do-Until / 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
})
您可以检查Pause状态,如果是,则使用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
})
实际上,您只需要一个按钮即可启动和暂停。这是一个非常基本的方法来说明我的想法,没有测试:
$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"
}
})
另一种方法是首先获取所有文件,将它们保存在集合中,然后在该点存储索引和暂停/恢复。但这带来了文件列表可能在此期间发生变化的风险。因此,真正“安全”的解决方案会更复杂。