PowerShell How-To
Leverage BITS for File Transfers with PowerShell
Background Intelligent Transfer Service is a useful tool for transferring large files or transferring to a system with connectivity issues.
- By Adam Bertram
- 08/03/2017
Performing simple file copies with PowerShell is fairly straightforward. Copy-Item will copy suffice when copying single files or whole folders of stuff. A problem arises, though, when the network you're transferring files across is flaky, the machine you're copying to doesn't maintain the connection it's supposed to or a number of other connectivity problems arise. Also, perhaps you're transferring some huge files across the wire that drastically affects overall network performance. Copy-Item has no way to account for any of these scenarios. In these situations, transferring files using BITS should be looked into.
Background Intelligent Transfer Service (BITS) has been around for a long time and is heavily used by Microsoft most popularly to deliver updates to all Windows computers through the Windows Update service. BITS is smart. BITS has native controls built-in to account for lots of different problems that may arise when transferring files.
BITS is leveraged in PowerShell through the BitsTransfer cmdlets.
PS> Get-Command -Noun BitsTransfer
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Complete-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Get-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Remove-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Resume-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Set-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Start-BitsTransfer 2.0.0.0 BitsTransfer
Cmdlet Suspend-BitsTransfer 2.0.0.0 BitsTransfer
The BITS cmdlets allow you to start, manage, suspend and remove BITS jobs. BITS transfer, unlike Copy-Item transfer, are done with jobs. This means that background jobs can be leveraged when performing large file copies which means much faster overall transfers!
Copying Files
To get started using the BITS cmdlets, let's just copy a single file. To start any BITS job, we need to use Start-BitsTransfer. When using BITS cmdlets like this, it's very similar to the syntax when using Copy-Item.
Start-BitsTransfer -Source C:\file.txt -Destination \\server\c$
Using the Source and Destination parameters is just the beginning of working with the Start-BitsTransfer cmdlet. Check out all of the other options we, by no means, have time for in this article.
S> help start-bitstransfer
NAME
Start-BitsTransfer
SYNOPSIS
Creates a BITS transfer job.
SYNTAX
Start-BitsTransfer [-Source] <String[]> [[-Destination] <String[]>] [-Asynchronous] [-Authentication {Basic | Digest | Ntlm | Negotiate | Passport}] [-Credential <PSCredential>]
[-Description <String>] [-DisplayName <String>] [-Priority {Foreground | High | Normal | Low}] [-ProxyAuthentication {Basic | Digest | Ntlm | Negotiate | Passport}] [-ProxyBypass
<String[]>] [-ProxyCredential <PSCredential>] [-ProxyList <Uri[]>] [-ProxyUsage {SystemDefault | NoProxy | AutoDetect | Override}] [-RetryInterval <Int32>] [-RetryTimeout <Int32>]
[-Suspended] [-TransferPolicy {Always | BelowCap | Capped | IgnoreCongestion | NearCap | None | NoSurcharge | NotRoaming | OverCapCharged | OverCapThrottled | PolicyUnrestricted |
Roaming | Standard | Unrestricted | UsageBased}] [-TransferType {Download | Upload | UploadReply}] [-UseStoredCredential {None | Proxy | Server}] [-Confirm] [-WhatIf]
[<CommonParameters>]
Using a Credential
Another great thing about using BITS over Copy-Item is the ability to use alternate credentials to perform the copy. If needing to copy files to a destination where the currently logged in user does not have access, we can simply use the Credential parameter to authenticate to the destination computer and begin the transfer.
Start-BitsTransfer -Source C:\file.txt -Destination \\server\c$ -Credential (Get-Credential)
Asynchronous Jobs
Perhaps you've got a huge set of files that need moved and need to initiate the transfer but continue on with the rest of your script. Since BITS always creates jobs under the covers, the Asynchronous parameter can be used to immediatelyreturn control back to the script upon execution. When the Asynchronous parameter is used, Start-BitsTransfer automatically returns a background job which can then be monitored. Below is an example:
$Job = Start-BitsTransfer -Source http://WebServer/HugeFile.zip -Destination C:\Folder -Asynchronous
while (($Job.JobState -eq "Transferring") -or ($Job.JobState -eq "Connecting")) `
{ sleep 5;} # Poll for status, sleep for 5 seconds, or perform an action.
Switch($Job.JobState)
{
"Transferred" {Complete-BitsTransfer -BitsJob $Job}
"Error" {$Job | Format-List } # List the errors.
default {"Other action"} # Perform corrective action.
}
Above we're starting a transfer, waiting for it to finish and then once complete, completing the transfer. This type of logic can be inserted anywhere in the script. It doesn't necessarily have to be right after the transfer is started.
There are a lot more things that are possible using the BITS cmdlets in PowerShell. These types of cmdlets are a great source of opportunity for developing bigger tools to create your own, robust file transfer module!
About the Author
Adam Bertram is a 20-year veteran of IT. He's an automation engineer, blogger, consultant, freelance writer, Pluralsight course author and content marketing advisor to multiple technology companies. Adam also founded the popular TechSnips e-learning platform. He mainly focuses on DevOps, system management and automation technologies, as well as various cloud platforms mostly in the Microsoft space. He is a Microsoft Cloud and Datacenter Management MVP who absorbs knowledge from the IT field and explains it in an easy-to-understand fashion. Catch up on Adam's articles at adamtheautomator.com, connect on LinkedIn or follow him on Twitter at @adbertram or the TechSnips Twitter account @techsnips_io.