【问题标题】:Powershell limiting BITS transfers to 4 at a timePowershell 一次将 BITS 传输限制为 4 个
【发布时间】:2023-04-07 10:17:01
【问题描述】:

我正在编写一个脚本,以使用 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--
    }
}

【问题讨论】:

    标签: powershell loops progress-bar microsoft-bits


    【解决方案1】:

    使用for-loop,您将在每次运行时将$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)

    【讨论】:

      【解决方案2】:

      感谢您的建议,成功了。我计划进一步完善我的代码,但这是目前我所拥有的。

      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 开关在控制台窗口中实际显示滚动进度条的结果不一致;完成的第一项工作往往会拖延并导致奇怪的视觉故障。省略开关并放弃进度条似乎可以解决问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 2014-04-11
        • 2013-05-27
        • 1970-01-01
        • 2014-04-22
        • 1970-01-01
        相关资源
        最近更新 更多