Subscribe Bookmark
Craige_Hales

Staff

Joined:

Mar 21, 2013

Control FTP from JMP with JSL

Here's some JSL to operate FTP through JMP 11's RunProgram function.  More about RunProgram below.


// this example is specific to Windows because of FTP and RunProgram issues


// you'll need to supply a proper site to open and replace


// anonymous... with proper credentials.




// for the example, build a "junk" directory in the temp folder


temp = Convert File Path( "$TEMP", windows ) || "junk"; // no trail back slash


Create Directory( temp ); // typically: "C:\Users\yourname\AppData\Local\Temp\junk"




// use JMP 11 RunProgram to run ftp; supply a ReadFunction to send all


// results to the JMP log


x = RunProgram(


  Executable( "ftp" ),


  Options( "-v -n" ),


  ReadFunction( Function( {this}, Write( this << read ) ) )


);




x << Write( "open ftp.example.com\!n" ); // site to open


x << Write( "user anonymous YOU@yourcompany.com\!n" ); // credentials


x << Write( "dir\!n" ); // look in the log for the file listing


x << Write( "lcd " || temp || "\!n" ); // local change directory...no trail back slash!


x << Write( "get README\!n" ); // fetch file 1


x << Write( "get index.html\!n" ); // and file 2


x << Write( "disconnect\!n" ); // or just bye if nothing else to do


x << Write( "bye\!n" ); // run program terminates when ftp terminates




// when ftp signals end-of-file for reading, RunProgram must


// really be finished.   Wait for it...


While( !(x << isReadEof), Wait( .01 ) );




// display the two files in the temp directory


Write( Load Text File( temp || "\!\README" ) );


Write( "\!n\!n\!n" );


Write( Load Text File( temp || "\!\index.html" ) );




Delete Directory( temp ); // clean up




Thanks to jara95 in this post for the FTP options.  FTP was not behaving at all without them.

RunProgram is a JSL function to control a command-line interface program on your computer.  FTP uses a command-line interface, MS-Paint does not.  A command-line program has two optional streams of data: an input stream of commands and an output stream of results.  RunProgram lets JMP write commands to the external program's input stream (stdin) and read output from the external program's output stream (stdout).

RunProgram has a description in the Help->Scripting Index with some examples.

The external program runs asynchronously from JMP.  Above, the variable x is the handle to the external program; don't overwrite x until you are done with it, and be sure to store the RunProgram return value in a variable like x so the RunProgram is not immediately lost.

Unless you use the simple RunProgram interface.  The simple interface runs synchronously, which means RunProgram does not return to JMP until the external program finishes.  The return value is all of the output from the external program.  Here's an example that should work on your Windows computer (be patient, it takes 5 seconds to do the 5 pings to your machine):


RP = RunProgram(


  Executable("PING.EXE"),


  Options( {"-n 5", "localhost"} ),ReadFunction("text"));



show(RP);




The output will look something like this

Pinging <your computer address> [::1] with 32 bytes of data:

Reply from ::1: time<1ms

Reply from ::1: time<1ms

Reply from ::1: time<1ms

Reply from ::1: time<1ms

Reply from ::1: time<1ms

Ping statistics for ::1:

    Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),

Approximate round trip times in milli-seconds:

    Minimum = 0ms, Maximum = 0ms, Average = 0ms

ReadFunction("text") enables this behavior; it is useful for programs that run to completion without a lot of supervision.

The FTP code might want a lot of supervision.  You might want to examine the output of a command before deciding what the next command should be.  You can do this with RunProgram, if you must, but it will be complicated and hard to explain and hard for the next person to maintain.  There is a WriteFunction, very similar to the ReadFunction.  You have to write JSL functions for both reading and writing and make them coordinate.  RunProgram will call them when there is data available on stdout or when stdin can accept more data.  One of the examples in the scripting index has a list of commands that it sends to CMD.EXE, one at a time, via the WriteFunction.  But it isn't really studying the stdout data in the ReadFunction...just printing it.

3 Comments
Community Trekker


Thanks so much for posting this.  It was exactly what I needed to know.  I can see lots of uses for RunProgram.

Community Member

This looks great, however I'm having some trouble getting the ftp, or your ping example, to run through JMP.

Opening a program like internet explorer through runprogram works fine, but ping, ftp, or even pointing to "C:\Windows\System32\ftp.exe" shows no action happening at all.

Any ideas would be really appreciated as this looks slightly more extendable than jan95's example

(resolved via email...) I failed to point out that the JSL Log window needs to be open to see results (and debug if something goes wrong).  The log window is closed by default.  View->Log (windows) or Window->Log (mac).

In particular, the output is not going to be in a CMD window (the black dos-box window).  Unless the program you run is cmd.exe.

Thanks!

Article Tags