Effective File Copying

Wed, Dec 3, 2008

Technology

Today my customer asked me how they should perform large file copies via scripting.  Normally I would suggest that you use the FileSystemObject (FSO) method and the file would make its way to the target folder.  But what if the file is a large file, or the connection to the target is a volatile connection?  Using the FSO method doesn’t offer any way to resume the copy if the copy is interrupted in mid stream.  And as for network traffic, FSO will consume all available network bandwidth during the copy.  Not so great if you are trying to do this as part of a background script. 

One option is to look at using RoboCopy.  Many people have posted comments about the power and functionality, but using RoboCopy requires that every one of your client machines has RoboCopy installed.  Not that big of a deal to distribute software to all of your client seats, right?  Guess it depends on the number of seats you are supporting…

Another option is to use the built in product that Microsoft uses for Updates and MSDN downloads:  Background Intelligent Transfer Service, or BITS.

Background Intelligent Transfer Service (BITS) transfers files (downloads or uploads) between
a client and server and provides progress information related to the transfers. You can also
download files from a peer.

Use BITS for applications that need to:

    * Asynchronously transfer files in the foreground or background.
    * Preserve the responsiveness of other network applications.
    * Automatically resume file transfers after network disconnects and computer restarts.

This little gem of software is already running on all of your Windows XP and higher clients and can be leveraged to meet all of your requirements.  The documentation for this software is pretty confusing so I decided to put together a sample list of commands that I gave to my customer for reference.

BITS is normally run as a background service but you can also run it interactively and use it to download that large file from a website.  To run it interactively you could use the syntax:

bitsadmin /transfer {JobName} {SourcePath} {DestinationPath} 

Keep in mind that if you close the interactive window you will terminate the download.  So this works great for you sitting at the desktop but not so much for an automated script…  So lets look at doing this as a regular job process.

First the legend outlines the variables and optional arguments:

{} = Specify your own values
[] = Optional values

{JobName} = Whatever you want - Must be unique among all jobs

{SourcePath} = Can be HTTP/HTTPS/UNC/DRIVE - use quotes for paths with spaces
                         Example 1:  "\\servername\folder\filename.zip"
                         Example 2:  "http://www.microsoft.com/downloads/myfile.zip"

{DestinationPath} = Include drive, folder, and name of file - Use quotes for paths with spaces
                               Example 1:  c:\filename.zip
                               Example 2:  "c:\my folder\filename.zip"

{UserName} = If necessary you can specify a Username for the connection
{Password} = If specifying a username then provide the password

Next here is some syntax you would use to schedule a job:

bitsadmin /create {JobName}
[OPTIONAL] bitsadmin /setcredentials {JobName} server negotiate {UserName} {Password}
bitsadmin /addfile {JobName} {SourcePath} {DestinationPath}
bitsadmin /setnotifycmdline {JobName} bitsadmin.exe "bitsadmin.exe /complete {JobName}"
bitsadmin /resume {JobName}

You may have noticed the curious entry on line 4 that configures the /setnotifycmdline option.  This is required if you are trying to script the copy of a file in a background service.  BITS requires that the job be “completed” before the file is made available.  So by adding this option the /command option is fired after the job has completed.  You could, of course, run any task you want in this option, like executing the file you just copied.

If you wanted to see the list of scheduled BITS jobs then the following syntax would be helpful:

bitsadmin /list [/verbose] {JobName}

Checking the state of the transfer can be done using the syntax:

bitsadmin /getstate {JobName}

Detailed information about the job can be seen using the syntax:

bitsadmin /info [verbose] {JobName}

And finally to remove active and completed jobs you would use the syntax:

bitsadmin /reset

The syntax is pretty straight forward once you get used to the command structure.  Using this tool you can script the transfer of large files and be sure that bandwidth won’t be drastically impacted and reboots and restarts of a computer will not interrupt the copy.  Do you have any experience with using BITS that you would care to share with me?

Check out more information about the BITS Admin Tool and also the BITS Return Codes.

And if you have any remaining questions feel free to drop me a comment.

Comments are closed.