From time to time you may find yourself creating scripts that require FTP support. Maybe you’re creating a script that will auto-update your web site contents or perhaps your script needs to check an ftp site for program updates or additional components to install.
In any of these cases, it can be helpful to add FTP functionality to your scripts. Unfortunately, the Windows Script Host does not provide any method for doing so natively. You can, however, create a usable workaround using the command-line FTP utility included with Windows.
Before we begin, let’s examine the command-line FTP utility. It’s called FTP.exe and is located in the System32 directory. Let’s take a peek at its command-line syntax.
-i Turns off interactive prompting during multiple file transfers.
-d Enables debugging.
-g Disables filename globbing (see GLOB command).
-s:filename Specifies a text file containing FTP commands; the commands will automatically run after FTP starts.
-a Use any local interface when binding data connection.
-A Login as anonymous.
-w:buffersize Overrides the default transfer buffer size of 4096.
host Specifies the host name or IP address of the remote host to connect to.
While you can use any of these switches to suit your needs, we’ll be concentrating on the –s switch. It allows us to specify an input file that contains a set of commands to be executed during the ftp session. This allows us to create an unattended ftp session.
In other words, we can execute the ftp command without having to input anything interactively on the command line. This is perfect for our scripting needs. All we need to do is determine the necessary commands and create the text file before we execute the FTP command.
In order to understand better what needs to be in the unattended ftp script, let’s take a look at an example ftp session. Here I’ve simply connected to my ftp site and downloaded a file. For security purposes, all sensitive information has been changed in the output below.
C:>ftp ftp.myserver.com
Connected to ftp.myserver.com.
220---------- Welcome to Pure-FTPd [TLS] ----------
220-You are user number 4 of 50 allowed.
220-Local time is now 13:14. Server port: 21.
220-IPv6 connections are also welcome on this server.
220-You will be disconnected after 15 minutes of inactivity.
User (ftp.myserver.com:(none)): USERNAME
331 User USERNAME OK. Password required
Password:
230-Your bandwidth usage is restricted
230-User USERNAME has group access to: USERNAME
230 OK. Current restricted directory is /
ftp> cd /public_html/pub/examples
250 OK. Current directory is /public_html/pub/examples
ftp> get word.vbs
200 PORT command successful
150 Connecting to port 61110
226-File successfully transferred
226 0.006 seconds (measured here), 146.10 Kbytes per second
ftp: 858 bytes received in 0.00Seconds 858000.00Kbytes/sec.
ftp> close
221-Goodbye. You uploaded 0 and downloaded 1 kbytes.
221 Logout.
ftp> bye
I’ve used a bold font to indicate the information that I typed manually at the interactive prompt. Essentially, these entries become the commands that we’ll use in the unattended ftp script. You could add any other ftp commands that you like to your session. Each line will be executed in turn whenever a prompt appears that required user input.
Here is what the unattended script for my ftp session would look like.
USER username
password
cd /public_html/pub/examples
get word.vbs
Notice that you can safely leave out the close and bye commands. The ftp session will be terminated as soon as it reaches the end of the script file.
There are a couple of things to keep in mind. First, know your ftp server. Some servers have different settings and may require other input. Second, avoid unexpected errors. Using commands like “binary” to specify a binary transfer mode for images or executables can prevent unwanted errors even though most servers will auto-sense the correct settings.
It’s also important to suppress unwanted confirmations. If you are sending or receiving multiple files at once (using mput or mget, respectively) you will be prompted to continue before each transfer. You can suppress this by using the “prompt n” command prior to using mput or mget or you can use the –i switch in your ftp command line.
In any case, test and retest your script to make sure it functions properly. If your script is going to be used for distribution, take care in making it fully compatible with all ftp servers on which it may be used.
At this point you can probably see where I’m going with this. We’ll be creating a WSH script that creates an unattended ftp script on the fly and then executes the ftp command. While the example in this article takes a very direct approach, try to keep in mind that this can be a very dynamic process if need be.
Don’t feel like you’re stuck creating simple line-by-line script solutions. You can create an upload script to synchronize a dynamic directory structure, for example. All you need to do is analyze the structure, gather the folder and file names, and use those to create your unattended script file. You’ll see that this is much easier than it sounds.
Let’s take a look at the code. To begin, we’re going to establish our server details and instantiate both the WshShell object and the FileSystemObject. We’ll also create a temporary text file that will be used as an unattended ftp script.
Const HOSTNAME = "ftp.myserver.com"
Const USERNAME = "Login"
Const PASSWORD = "password"
Set WshShell = CreateObject("WScript.Shell")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile = objFso.CreateTextFile("session.txt")
Next, we’ll add the necessary ftp commands by writing them to the ftp script file.
With objFile
.WriteLine "USER username"
.WriteLine "password"
.WriteLine "cd /public_html/pub/examples"
.WriteLine "get word.vbs"
.Close
End With
Finally, we’ll execute the ftp command using the WshShell object’s Exec method.
For the sake of compatibility, I’ve used an environmental variable in my path. Be aware that you cannot do this if you intend to run this script as a Scheduled Task. Scheduled Tasks do not support the use of environmental variables in WSH scripts and will require you to hard code the path.
objFso.DeleteFile "session.txt", vbTrue
All that’s left now is a little cleanup to remove the temporary text file that we’ve created. Now let’s take a look at some potential security vulnerabilities that we should take into consideration.
As you can see with this example, the username and password required for this ftp login are stored unencrypted in a plain text file. As you can imagine, this poses a potential security risk.
It would be much safer if the user had to provide this information at the time of script execution. You could easily ask the user for a password using an input box, for example.
strPassword = InputBox("Please enter the FTP password:", _
"Enter Password")
If you are launching this script from a command line, you might want to consider passing the password as an attribute to the script as I’ve done in the following example.
If (WScript.Arguments.Count > 0) Then
Set colArgs = WScript.Arguments
strPassword = colArgs.Item(0)
Else
strPassword = ""
End If
Whatever way you choose to do for this, keep in mind that you never know when you’ll be dealing with prying eyes and, unfortunately, WSH scripts are stored in plain text format.
Also, keep in mind that you are writing the FTP password to a temporary plain text file as well. Make sure that the temporary file is deleted immediately after the FTP command completes.
In any case, I hope I’ve opened up the doors for you to add ftp functionality to your scripts. This can provide a very dynamic aspect to your scripting repertoire. Until next time, keep coding!