Powershell 一次将 BITS 传输限制为 4
Powershell limiting BITS transfers to 4 at a time
我正在编写一个脚本,使用 BITS 将 Office 365 ProPlus 二进制文件传输到 12 个单独的文件共享。我还想在屏幕上显示这些传输的进度。我的问题是,我想将同时传输的 BITS 数量限制在一次不超过 4 个。当一项工作完成后,我想开始队列中的下一项工作并继续接收进度,直到所有工作完成。
这就是我目前所拥有的。我首先使用此函数为处于暂停状态的所有网络位置创建我的所有 BITS 作业。
function Start-BinaryTransfer
{
[CmdletBinding()]
param
(
[array]$DistrictsToUpdate
)
$Source = "$BaseSource$UpdateChannel"
if ("All" -in $DistrictsToUpdate.Split(','))
{
foreach ($Destination in $ReposList)
{
Copy-Item -Path $Source -Destination $($Destination.Location + '\') -Filter { $_.PSisContainer } -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $Source -Recurse | Where-Object{ $_.PSisContainer } | ForEach-Object {
$spath = $_.FullName.Remove(0, $Source.Length + 1)
$BITSJobs += Start-BitsTransfer -Source $Source$spath\*.* `
-Destination "$($Destination.Location)$UpdateChannel$spath" `
-DisplayName "$($Destination.District) File Transfer" `
-Description "Transferring from [$Source] to [$($Destination.Location)$UpdateChannel]" `
-Suspended
}
}
}
创建完所有作业后,我尝试使用此 While 循环一次启动 4 个作业,并显示进度。不幸的是,实际行为是它会尝试同时启动所有 12 个作业,这会导致网络资源陷入困境。
While (Get-BitsTransfer | Where JobState -EQ "Suspended")
{
Get-BitsTransfer | Where JobState -EQ "Suspended" | ForEach-Object {
for ($JobsCount = 0; $JobsCount -le 4; $JobsCount++)
{
if ($JobsCount -lt 4)
{
Resume-BitsTransfer -BitsJob $_ -Asynchronous
Get-BitsTransfer | Where JobState -EQ "Transferring" | ForEach-Object {
Write-Progress `
-Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Status "$($_.Description)" `
-CurrentOperation "$([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100)) % Complete" `
-PercentComplete $([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100))
}
}
}
}
if (Get-BitsTransfer | Where JobState -EQ "Transferred")
{
Get-BitsTransfer | Where JobState -EQ "Transferred" | Complete- BitsTransfer
$JobsCount--
}
}
使用 for
循环,您将每隔 运行
将 $JobsCount
重置为 0
for ($JobsCount = 0; $JobsCount -le 4; $JobsCount++)
像这样的东西应该可以工作(对当前代码进行最少的更改):
$JobsCount = 0
While (Get-BitsTransfer | Where JobState -EQ "Suspended")
{
Get-BitsTransfer | Where JobState -EQ "Suspended" | ForEach-Object {
# remove for-loop
if ($JobsCount -lt 4)
{
$JobsCount++
...
您还必须修改您的 while
-loop,目前它会在 JobState
"Suspended"
没有更多工作时退出,但您仍然需要等待工作使用 JobState
"Transferring"
并在 "Transferred"
时完成它们。建议:While ((Get-BitsTransfer) -ne $null)
或者更简单的While (Get-BitsTransfer)
感谢您的建议,成功了。我计划进一步完善我的代码,但这是我目前可用的代码。
function Update-JobProgress
{
[CmdletBinding()]
param ()
Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferring") -and ($_.DisplayName -Like "*File Transfer") } | ForEach-Object {
Write-Progress -Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Status "$($_.Description)" `
-CurrentOperation "$([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100)) % Complete" `
#-PercentComplete $([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100))
}
}
While (Get-BitsTransfer)
{
$JobsCount = (Get-BitsTransfer | Where-Object { ($_.JobState -ne "Suspended") -and ($_.DisplayName -Like "*File Transfer") }).Count
Get-BitsTransfer | Where-Object JobState -EQ "Suspended" | ForEach-Object {
if ($JobsCount -lt 4)
{
Resume-BitsTransfer -BitsJob $_ -Asynchronous
$JobsCount++
}
}
Update-JobProgress
if (Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferred") -and ($_.DisplayName -Like "*File Transfer") })
{
Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferred") -and ($_.DisplayName -Like "*File Transfer") } | ForEach-Object {
Write-Progress `
-Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Completed
$_ | Complete-BitsTransfer
$JobsCount--
}
}
}
在我的测试中,我发现使用 -PercentComplete 开关在控制台中实际显示滚动进度条的结果不一致 window;完成的第一份工作往往会拖延并导致奇怪的视觉故障。省略开关并放弃进度条似乎可以解决问题。
我正在编写一个脚本,使用 BITS 将 Office 365 ProPlus 二进制文件传输到 12 个单独的文件共享。我还想在屏幕上显示这些传输的进度。我的问题是,我想将同时传输的 BITS 数量限制在一次不超过 4 个。当一项工作完成后,我想开始队列中的下一项工作并继续接收进度,直到所有工作完成。
这就是我目前所拥有的。我首先使用此函数为处于暂停状态的所有网络位置创建我的所有 BITS 作业。
function Start-BinaryTransfer
{
[CmdletBinding()]
param
(
[array]$DistrictsToUpdate
)
$Source = "$BaseSource$UpdateChannel"
if ("All" -in $DistrictsToUpdate.Split(','))
{
foreach ($Destination in $ReposList)
{
Copy-Item -Path $Source -Destination $($Destination.Location + '\') -Filter { $_.PSisContainer } -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $Source -Recurse | Where-Object{ $_.PSisContainer } | ForEach-Object {
$spath = $_.FullName.Remove(0, $Source.Length + 1)
$BITSJobs += Start-BitsTransfer -Source $Source$spath\*.* `
-Destination "$($Destination.Location)$UpdateChannel$spath" `
-DisplayName "$($Destination.District) File Transfer" `
-Description "Transferring from [$Source] to [$($Destination.Location)$UpdateChannel]" `
-Suspended
}
}
}
创建完所有作业后,我尝试使用此 While 循环一次启动 4 个作业,并显示进度。不幸的是,实际行为是它会尝试同时启动所有 12 个作业,这会导致网络资源陷入困境。
While (Get-BitsTransfer | Where JobState -EQ "Suspended")
{
Get-BitsTransfer | Where JobState -EQ "Suspended" | ForEach-Object {
for ($JobsCount = 0; $JobsCount -le 4; $JobsCount++)
{
if ($JobsCount -lt 4)
{
Resume-BitsTransfer -BitsJob $_ -Asynchronous
Get-BitsTransfer | Where JobState -EQ "Transferring" | ForEach-Object {
Write-Progress `
-Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Status "$($_.Description)" `
-CurrentOperation "$([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100)) % Complete" `
-PercentComplete $([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100))
}
}
}
}
if (Get-BitsTransfer | Where JobState -EQ "Transferred")
{
Get-BitsTransfer | Where JobState -EQ "Transferred" | Complete- BitsTransfer
$JobsCount--
}
}
使用 for
循环,您将每隔 运行
$JobsCount
重置为 0
for ($JobsCount = 0; $JobsCount -le 4; $JobsCount++)
像这样的东西应该可以工作(对当前代码进行最少的更改):
$JobsCount = 0
While (Get-BitsTransfer | Where JobState -EQ "Suspended")
{
Get-BitsTransfer | Where JobState -EQ "Suspended" | ForEach-Object {
# remove for-loop
if ($JobsCount -lt 4)
{
$JobsCount++
...
您还必须修改您的 while
-loop,目前它会在 JobState
"Suspended"
没有更多工作时退出,但您仍然需要等待工作使用 JobState
"Transferring"
并在 "Transferred"
时完成它们。建议:While ((Get-BitsTransfer) -ne $null)
或者更简单的While (Get-BitsTransfer)
感谢您的建议,成功了。我计划进一步完善我的代码,但这是我目前可用的代码。
function Update-JobProgress
{
[CmdletBinding()]
param ()
Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferring") -and ($_.DisplayName -Like "*File Transfer") } | ForEach-Object {
Write-Progress -Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Status "$($_.Description)" `
-CurrentOperation "$([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100)) % Complete" `
#-PercentComplete $([math]::Floor($_.BytesTransferred / $_.BytesTotal * 100))
}
}
While (Get-BitsTransfer)
{
$JobsCount = (Get-BitsTransfer | Where-Object { ($_.JobState -ne "Suspended") -and ($_.DisplayName -Like "*File Transfer") }).Count
Get-BitsTransfer | Where-Object JobState -EQ "Suspended" | ForEach-Object {
if ($JobsCount -lt 4)
{
Resume-BitsTransfer -BitsJob $_ -Asynchronous
$JobsCount++
}
}
Update-JobProgress
if (Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferred") -and ($_.DisplayName -Like "*File Transfer") })
{
Get-BitsTransfer | Where-Object { ($_.JobState -EQ "Transferred") -and ($_.DisplayName -Like "*File Transfer") } | ForEach-Object {
Write-Progress `
-Id $([math]::Abs($_.DisplayName.GetHashCode())) `
-Activity "$($_.DisplayName)" `
-Completed
$_ | Complete-BitsTransfer
$JobsCount--
}
}
}
在我的测试中,我发现使用 -PercentComplete 开关在控制台中实际显示滚动进度条的结果不一致 window;完成的第一份工作往往会拖延并导致奇怪的视觉故障。省略开关并放弃进度条似乎可以解决问题。