Quick Links

A lesser-known feature of Windows is the Background Intelligent Transfer Service (BITS). This is a service, primarily for programmers and system administrators, that works to transfer files to and from HTTP and SMB servers.

Here are some of the incredibly useful features of this service:

  • Handle Network Interruptions
  • Pause and Resume, even from a Reboot
  • Take into account Network Cost

In this article, we explore how to use BITS in PowerShell to perform and control file transfer operations.

Getting Started with BITS

The BITS cmdlets are actually built-in as default PowerShell commands. We can see what those commands are by running

        Get-Command | Where-Object Source -EQ 'BitsTransfer'
    

.

Although PowerShell 7 is cross-platform, this relies on a Windows-specific service, so this functionality will not be available on other operating systems.

Start-BitsTransfer

To create a new BITS transfer job, of which you can then add or remove files to, use the Start-BitsTransfer cmdlet. To simply transfer files between two locations, you can define a source and destination as shown below.

        $Params = @{
"Source" = '\\Server01\C$\TestFile.txt'
"Destination" = '\\Server02\C$\TestFile.txt'
}

Start-BitsTransfer @Params

To take advantage of the other BITS cmdlets, it is best to give the BITS transfer job a proper DisplayName that can then be referenced later. Using the same @Params declaration, we can add a display name, in this case TestTransfer.

        Start-BitsTransfer @Params -DisplayName 'TestTransfer'

By default, the BITS transfer will run at a Foreground priority, which implies the highest transfer speed available. This can be easily changed using one of the available priorities listed below.

  • Foreground (default): Transfers the job with the highest priority and competes for network resources with other applications.
  • High: Transfers with a higher priority than normal, but still relies on using the idle network bandwidth of the client computer.
  • Normal: Same as high priority but with a lower priority.
  • Low: Same as normal priority but with the lowest possible priority.Start-BitsTransfer @Params -DisplayName 'TestTransfer' -Priority 'Normal'

As mentioned in the beginning, BITS has the unique ability to take network cost into account. To do this, we use the TransferPolicy parameter.

        $Params = @{
"Source" = '\\Server01\C$\TestFile.txt'
"Destination" = '\\Server02\C$\TestFile.txt'
"DisplayName" = 'TestTransfer'
"Priority" = 'Normal'
"TransferPolicy" = 'Capped'
}

Start-BitsTransfer @Params

In this example, Capped implies that there is an upper bound for the network traffic and to respect that boundary.

Finally, to start this job in the background and return our console for use, passing the Asynchronous parameter allows us to background the job.

        Start-BitsTransfer @Params -Asynchronous

Get-BitsTransfer

What if we wanted to check out all running BITS jobs, that's simple with the Get-BitsTransfer cmdlet.

Since we named our transfer with TestTransfer earlier on, it's easy to find. Running Get-BitsTransfer by itself will list all running jobs.

Add-BitsFile

Now that we have retrieved our transfer, we can actually add additional files to this transfer simply by calling Add-BitsFile.

        $Job = Get-BitsTransfer -Name 'TestTransfer'

$Params = @{
"Source" = '\\Server01\C$\TestFile2.txt'
"Destination" = '\\Server02\C$\TestFile2.txt'
}

$Job | Add-BitsFile @Params

Suspend-BitsTransfer

With all these files transferring, sometimes there is a need to pause a transfer. This could occur for many reasons. Often it's because of a congested network or a system needs to be rebooted in the middle of a transfer. This is simple with BITS, by using the Suspend-BitsTransfer functionality.

        $Job | Suspend-BitsTransfer

Resume-BitsTransfer

Naturally, at some point we will need to start the job again, and again it's as simple as passing the job into Resume-BitsTransfer.

        $Job | Resume-BitsTransfer

Set-BitsTransfer

If a job is still active, it's possible to update the job with new settings using the Set-BitsTransfer cmdlet. In the example below, we are setting the job to the highest possible network priority. Originally we set the job to Normal, but we need to get the job done sooner so we use Foreground.

        $Job | Set-BitsTransfer -Priority 'Foreground'

Complete-BitsTransfer

Perhaps we have suspended a job and we are ready to finish the transfer. Using the Complete-BitsTransfer cmdlet, we can tell BITS to finish all active transfer jobs.

        Get-BitsTransfer | Complete-BitsTransfer

Remove-BitsTransfer

Finally, if we just need to remove a job, running or not, we can use the Remove-BitsTransfer cmdlet.

        Get-BitsTransfer -Name "JobToBeRemoved" | Remove-BitsTransfer -Confirm:$False

Using -Confirm:$False, means that the jobs will be removed without a prompt for confirmation.

Additional BITS Capabilities

The examples shown in the processes above were concentrated on the downloading of a file from one server to another. BITS has the ability to upload a file as well, even with authentication.

        $Params = @{
"Source" = '\\Server01\C$\TestFile.txt'
"Destination" = '<http://server02/uploaddir/testfile.txt>'
"TransferType" = 'Upload'
}

Start-BitsTransfer @Params

It's important to note that the default behavior of BITS is to download multiple files automatically. This is not the same behavior with upload, and to work around this limitation you can pipe in multiple files to the Start-BitsTransfer cmdlet.

If the destination server is protected by authentication, you can specify the type such as Basic, Digest, NTLM, Negotiate, or Passport using the Authentication parameter. Of course, by using authentication, you will need to pass in a credential which can be done easily with the Credential parameter. This takes standard PSCredential objects and works well to keep your secrets secure and encrypted within your scripts.

Conclusion

BITS is a fantastic way to control file transfers between servers and between web servers. With the ability to suspend and resume, it is easy to control the transfer of files across network links, even those that need to be moderated due to potential cost.

Despite this only working on Windows, BITS is a powerful tool to integrate into your scripts and precisely control file transfers, even across reboots. Potentially replacing traditional Windows utilities like Robocopy, BITS adheres to the PowerShell methodology and with the ability to background transfers as jobs, seamlessly integrates into existing automation and scripts.