PC Commands from the AS/400

General
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Have you ever had a user ask you if it would be possible to kick off a PC program from the AS/400? Perhaps he wanted to be able to open up the Windows calculator program while he was in your green-screen accounts receivable application. Or maybe he wanted to be able to type a quick Word document to a customer while he was fulfilling an order. Whatever the reason, there are times when it’s handy to be able to execute PC commands and applications from the AS/400.

STRPCCMD and RUNRMTCMD

The original method of executing PC commands from the AS/400 was to use Start PC Command (STRPCCMD). This command works over non-TCP/IP connections only, such as on a PC that is connected via NetManage’s NS/Router. To use this command, you must first start the PC organizer using the Start PC Organizer (STRPCO) command. This is because STRPCCMD runs inside the old PC Support/400 shell. PC Support/400 was the precursor to Client Access/400; because IBM has changed the text on this command to indicate it is now a Client Access tool but don’t be fooled. PC Support/400 is still the original product that has been around since the very first version of OS/400. The PC must have Client Access loaded on it to use this command. To execute the command, type STRPCCMD from an AS/400 command line and press F4 to prompt it.

The Run Remote Command (RUNRMTCMD) function allows you to execute PC commands from the AS/400 over both SNA and TCP/IP connections. When IBM upgraded the 16-bit PC Support/400 product to the 32-bit Client Access/400, it also provided for several new connectivity options, most notably TCP/IP. With that upgrade came several new interfaces, including the RUNRMTCMD utility. RUNRMTCMD requires that the PC client have Client Access/400 or Client Access Express on it. RUNRMTCMD uses a client/server approach to executing PC commands. In this case, the PC acts as the server and the AS/400 is the client. In order to use the server portion of this scenario, your PC must be running the Incoming Remote Command daemon program, CWBRXD.EXE, which is included with Client Access. For more information on using RUNRMTCMD, check out “Top Tips: Connectivity” and look under the subheading How to Run PC Commands from Your AS/400 in the September 1998 issue of MC.

CommandServerJSK

Until now, STRPCCMD and RUNRMTCMD were your only options for executing commands on the PC from the AS/400. However, both commands require that your users have Client Access loaded on their PCs. While this may not be a big deal for some IT professionals, others, for many reasons, don’t want to load Client Access on their users’ PCs. For these folks, there are alternatives.

There are several methods that can be used to execute PC commands from the AS/400 that do not require Client Access. The first is through the use of Sockets. Sockets are a way of treating TCP connections as if they were any other type of file I/O. That is, to a program that understands the TCP/IP protocol, data coming across a Socket appears as if it were coming from a locally stored database or the standard input. Sockets use a
“connection-oriented” approach over TCP/IP. That is, the Socket server listens for requests coming across a given port over TCP/IP. When the request is found, the server acknowledges the request to the client, which has been patiently waiting for the acknowledgment. While the client is formatting the next request, the server is patiently waiting. In other words, both the client and the server remain in contact for the duration of the life cycle of the Socket event. This is what’s known as a connection-oriented approach.

With the advent of the UNIX-type APIs and the ability of RPG IV and other ILE languages to use these APIs, the AS/400 now has the ability to write to and read from Sockets. That’s what you’re going to take advantage of with the CommandServerJSK utility. I’m not going to go into details on how to use the RPG IV Socket program used in this utility, as all that information has been covered before. For an in-depth look at RPG IV and Sockets, check out “Servlets, Sockets, and RPG” by Jeff Markham in the July 2000 issue of MC.

Just like IBM’s RUNRMTCMD, CommandServerJSK works on the client/server model. That is, CommandServerJSK is the server, and your RPG IV Socket program is the client that sends requests to it. In this case, the requests are PC commands to execute. All code for this utility and the others discussed in this article can be downloaded from Midrange Computing’s Web site at www.midrangecomputing.com/mc. Download the code for this utility and compile the AS/400 command, EXPCCMD, and the RPG IV program PCCMD0R1 on the AS/400. You’ll also need to compile the Java program CommandServerJSK.java on your PC. If you don’t already have it, you’ll need a Java compiler such as the one available free from Sun Microsystems at www.javasoft.com. Also, if you’re going to install the Java programs on your users’ PCs, they’ll need, at the minimum, the Java Runtime Environment (JRE). You can download this free tool from Sun’s Web site at www.javasoft.com and install it on the users’ PCs along with the Java classes from this article. The JRE will allow the users’ PCs to run Java applications without requiring the full Java development kit.

CommandServerJSK is a Java program I wrote that listens for connections on any port you specify and then uses the Java Runtime.exec Process to execute those commands on the PC. If you’re new to Java programming, study this code as it demonstrates many basic Java programming principles, including threads. The instructions for using the utility and the theory behind how it works are included in a ReadMe file in the downloadable code available from the MC Web site.

All activity for the Socket and command will be echoed to a dialog window on the users’ desktops. The best thing about this technique is that it will allow you to run PC commands on any platform that supports Java. However, for those of you not comfortable with Java yet, I’ve included a Visual Basic (VB) version of this utility, called CommandServerVB, for download from the MC Web site. This program also uses Sockets to connect to the client and then uses VB’s SHELL command to execute PC commands.

CommandServerJDQ

If you don’t want to learn how to use Sockets, don’t worry. I’ve created a variation on the CommandServerJSK program that uses data queues instead of Sockets for communication.


The AS/400 has supported data queues since the very beginning, and MC has provided many examples of writing to and reading from data queues in RPG. In the CommandServerJDQ utility (Figure 1), I expand on that basic idea and use data queues as the means to communicate with my JavaServer program on the PC. The CommandServerJDQ Java application uses the AS/400 Java Access classes, available as part of the JTOPEN.jar file available for download from IBM at www.as400.ibm.com/toolbox or on your V4R4 AS/400 in the directory /QIBM/ProdData/HTTP/Public/jt400/lib, to provide the means of creating and reading AS/400 data queues. If you’re new to Java programming, the CommandServerJDQ.java source file is a great file to study, as it demonstrates many basic AS/400 Java techniques, including connecting to the AS/400, creating and reading data queues on the AS/400, and converting text from EBCDIC to Unicode. Download the code for this utility, which includes two AS/400 source files (the command EXPCCMD2 and the command processor PCCMD0R2) as well as the Java source file CommandServerJDQ.java from MC, and compile the AS/400 code. You’ll need to make a couple of minor modifications (detailed in the ReadMe file included in the download) to the Java source file before you compile it. Like the CommandServerJSK utility, the instructions for using and modifying the source files and the theory behind how they work can be downloaded as part of this download file from MC’s Web site. When the application executes, you’ll be presented with a status window like that shown in Figure 2.

Alternatives

So far, I’ve discussed only a couple of different options for running PC commands from the AS/400. There are many more that I didn’t cover. These include using a VB program to read commands from AS/400 data queues; using Java’s Remote Method Invocation (RMI) to pass the command string from a Java program running on the AS/400 to a Java program running on the PC; using C++ to duplicate the Sockets and data queue examples; running an FTP server on the PC that executes commands via the RCMD parameter; or even using JINI, Common Object Request Broker Architecture (CORBA), or Microsoft’s Simple Object Access Protocol (SOAP)to execute your PC commands. The fact that IBM gave you only two choices for executing PC commands doesn’t mean that these are your only options. Be creative and see what you can come up with on your own!

//***************************************************************

//

// To Compile:
//

// From a PC command line (must have JDK 1.1.8 or higher)
//

// javac CommandServerJDQ.java -deprecation
//

//***************************************************************

//

// This java class will execute PC commands via a Data Queue.
// It will accept commands from an AS/400. When this class is
// started, it will connect to the AS/400 and create a data
// queue on the AS/400. AS/400 applications, such as those
// written in RPG, can then send a PC command request, including
// the fully qualified path name, to the data queue. Once it
// arrives on the data queue it will be read and removed by this
// class and executed by the java Runtime() class.


//

//***************************************************************

import java.io.*;
import java.net.*;
import java.awt.*;
import CloseWindowAndExit;
import java.lang.Process;
import com.ibm.as400.access.*;

public class CommandServerJDQ extends Frame
{

private TextArea commandWindow;

private int ev = 0;

private AS400 host = null;

private String dqData = null;

private String Command_To_Execute = “”;

private byte [] IPKey;

private boolean Continue = true;

private int IPLen = 20;

public CommandServerJDQ()

{

super (“CommandServerJDQ”);

commandWindow = new TextArea( “”, 0,0,

TextArea.SCROLLBARS_VERTICAL_ONLY);

add (commandWindow, BorderLayout.CENTER);

setSize(400, 150);

setVisible( true );

commandWindow.setEditable(false);

commandWindow.setVisible(true);

commandWindow.append(“Connecting to AS/400...”);

//**********************************************************

// Get IP address of device CommandServerJDQ is running on

// and then convert it from UNICODE to EBCDIC

//**********************************************************

try {

InetAddress MyHost = InetAddress.getLocalHost();

String MyIP = MyHost.getHostAddress();

AS400Text IPValue = new AS400Text(20);

IPKey = IPValue.toBytes(MyIP);

}

catch(UnknownHostException uh)

{ System.out.println(“Unable to retrieve IP Address “ + uh);

System.exit(0); }

}

public void runDataQueueServer()

{
//****************************************

// Connect to the AS/400
//****************************************

host = new AS400();

commandWindow.append(“ ...connected...”);

//*************************************


// Create the Keyed DataQueue object

//*************************************

KeyedDataQueue dq =

new KeyedDataQueue(host, “/QSYS.LIB/SHANNON.LIB/PCCMDDQ.DTAQ”);

try {

dq.create(20, 500);

commandWindow.append(“ Data Queue SHANNON/PCCMDQ created ”); }

catch(Exception ce)

{ commandWindow.append(“ Data Queue already exists.”); }

//*****************************************************

// Loop to allow continuous command processing serving

//*****************************************************

while (Continue) {

try {

commandWindow.append(“ Listening for commands...”);

//*****************************************************

// read data from the queue by the local IP address.

// The “-1” parameter means to wait for an entry to

// be placed on the Data Queue

//*****************************************************

KeyedDataQueueEntry dqData = dq.read(IPKey, -1, “EQ”);

//****************************************************************

// Now extract the command from the Keyed Data Queue Entry object

//*****************************************************************

byte[] data = dqData.getData();

int Command_Length = 500;

AS400Text textConverter = new AS400Text(Command_Length);

String Cmd_Str = (String) textConverter.toObject(data);

Command_To_Execute = Cmd_Str.trim();

commandWindow.append(“ Command to be Executed = “ +

Command_To_Execute);

//*****************************

// Now execute the command

//*****************************

RunCommand(); }

catch(AS400SecurityException se)

{ commandWindow.append(“ Security Exception “ + se);

Continue = false; }

catch(ConnectionDroppedException cd)

{ commandWindow.append(“ Connection Dropped Exception “ +
cd);

Continue = false; }

catch(ErrorCompletingRequestException er)

{ commandWindow.append(“ Error completing request “ + er);

Continue = false; }

catch(IOException ioe)

{ commandWindow.append(“ IO Exception “ +ioe);

Continue = false; }

catch(IllegalObjectTypeException io)


{ commandWindow.append(“ Ilegal Object Type Exception “ +
io);

Continue = false; }

catch(InterruptedException ie)

{ commandWindow.append(“ Interrupted Exception “ + ie);

Continue = false; }

catch(ObjectDoesNotExistException ne)

{ commandWindow.append(“ Object Does Not Exist Exception “ +
ne);

Continue = false; } }

// Disconnect using data queues

host.disconnectService(AS400.DATAQUEUE); }

//***************************************************

// Execute the PC command retrieved from Data Queue
//***************************************************

public void RunCommand()

{

try {

Runtime rt = Runtime.getRuntime();

Process ps = rt.exec(Command_To_Execute);

try { ps.waitFor(); }

catch (IllegalArgumentException ia)

{ commandWindow.append(“Illegal Argument “ + ia);}

catch (InterruptedException i)

{ commandWindow.append(“waitFor() method failed...” + i +
“ ”); }

ev = ps.exitValue();

if (ev == 1)

{commandWindow.append(“Command “ + Command_To_Execute +

“ended abnormally ”);}

commandWindow.append(“ ” + Command_To_Execute +

“ completed normally”);

}

catch (IOException e)

{ commandWindow.append(“Command did not start :” + e + “ ”); }
}

//***************

// Main method
//***************

public static void main (String args[])

{

CommandServerJDQ s = new CommandServerJDQ();

s.addWindowListener( new CloseWindowAndExit());

s.runDataQueueServer();

}

}

Figure 1: As shown in the Java source for CommandServerJDQ, you can use data queues to communicate with a JavaServer program on a PC.


PC_Commands_from_the_AS-_40007-00.png 398x143

Figure 2: When you start CommandServerJDQ, you’ll see this dialog window.


BLOG COMMENTS POWERED BY DISQUS