One of the functions provided with Client Access/400 is the Host Command program. After installing the Windows client, the Host Command program is in your Client Access/400 program group. When you run Host Command, you are prompted to enter the AS/400 command that you want to run. The command is then submitted to the default system.
The Host Command program, as provided, works in a peculiar manner. After entering the command to run, another window is displayed. The other window is apparently a DOS box, in which the command is running. Although error and completion messages are output from the Host Command, you probably wont see them, as the DOS box closes immediately after displaying the messages.
As an alternative, you can create your own version of the Host Command function using the Client Access/400 APIs. The program shown here uses Visual Basic. By creating this version of the Host Command program, youll not only have a better version of the function, but youll also see how to use the Submit Remote Command APIs. If you develop Windows programs using Visual Basic, there may be times when you need to use the submit remote command function within those programs. You can modify the code shown here as needed. Features of the Submit Remote Command Program
The Submit Remote Command program provides some helpful improvements to the Client Access/400 Host Command program. Figure 1 shows the Submit Remote Command dialog with each of its elements labeled.
You choose the AS/400 system to which the command is submitted from a list of AS/400s to which you have router sessions. The default system is the first entry in the list. The list is shown in the lstSystemName control.
After submitting a command, a status message is shown at the bottom of the window. The status message is in the lblMessageLine control. The status message is sent for either successful or unsuccessful completion of the command.
Finally, you can review all of the messages that were sent as a result of running the command. You review messages by clicking the cmdShowMessages control. Figure 2 shows a sample of the messages sent for the erroneous WRKOUQT command. Figure 3 shows a sample of a successful command.
Program Requirements
You need only a few things to create this program. First, you need the Client Access/400 for Windows 3.1 software. Verify that you have two files, EHNAPPC.DLL and EHNSRW.DLL, installed on your PC. Those files will probably be in your CAWIN directory or your WINDOWSSYSTEM directory. The files contain the code needed for the Client Access/400 APIs.
Youll also need Visual Basic. I created and tested the program with Visual Basic 3.0 for Windows. Although youll want the Professional Version for most projects involving AS/400 client/server programming, you can create the Submit Remote Command program with the Standard Version.
Finally, youll need to create the Submit Remote Command form and enter the source code. Use Figure 1 as a guide for creating the form. You need to create module RMTCMD.BAS (Figure 4) and RMTCMD.FRM (Figures 5 through 9). The code for this project is also available on the Midrange Computing BBS system, in file area 2. The BBS number is listed on page 2 of this issue.
How the Program Works
The APIs are declared in the RMTCMD.BAS module (Figure 4). The program uses two APPC APIs and three Remote Command APIs. These are:
EHNAPPC_IsRouterLoadedto verify that the Client Access/ 400 router is loaded.
EHNAPPC_QuerySystemsto get the list of systems to which the router is connected, and the name of the default system.
EHNSR_SubmitCommandto submit the remote command to the system that you choose.
EHNSR_GetMessageto get the messages returned as a result of submitting the command.
EHNSR_StopConversationto stop the APPC conversation used by the Submit Command APIs.
Visual Basic requires the API function declarations so that it can find the function code (in either the EHNAPPC.DLL or EHNSRW.DLL files), and so that it knows how to work with the parameters.
The RMTCMD.BAS module also includes declarations for other fields and constants used in the program.
When you start the program, the code shown in the Form_Load (Figure 5) is executed. This routine checks for an active router connection. If the router is not active, a
message box is displayed and the program ends. Next, the routine gets the list of systems to which the router is connected. After getting the list, it picks each system name out of the list, and puts the names into a Visual Basic drop-down list box. You choose the system to which the command is sent from the list box.
After typing in a command, you click the Submit Command button. That runs the code in the cmdSubmit_Click routine (Figure 6). If you didnt enter a command, a message box is displayed telling you that a blank command can not be submitted. If you did enter some characters, the routine strips out any trailing control characters (e.g., carriage return, line feed). If trailing control characters are not removed, the AS/400 rejects the command.
The routine then submits the command to the AS/400. When you submit the command, you also provide a reply message buffer. Any error or status messages go into the reply buffer. The messages do not include inquiry messages, as there is no way to respond to a message in the reply buffer.
After running the submit command API, cmdSubmit_Click checks the return code from the API. Depending on the return code, a message is displayed on the form. The Show Messages command button is also enabled to let you look at messages from the reply buffer.
The code in cmdShowMessages_Click (Figure 7) runs when you click the Show Messages button. This routine retrieves messages from the reply buffer, formats them, and displays them in a Visual Basic message box. The submit remote command API can put up to 10 reply messages into the message buffer. The cmdShowMessages_Click routine loops through the reply buffer until there are no more messages to retrieve from the buffer.
If you submit more than one command, the txtCommand_Change routine (Figure 8) runs whenever you type in a new command. This routine disables the Show Messages command button. You cannot click the button until after submitting the new command.
Finally, the program ends when you click the Exit button. The cmdExit_Click routine runs (Figure 9). The routine calls the Stop Conversation API to free the resources used by the Submit Command function, then ends the Visual Basic program.
References
The Submit Remote Command API and the APPC APIs used in this program are documented in IBMs Client Access/400 for Windows 3.1 API and Technical Reference manual (SC41-3531). The documentation describes each API function, and also the return codes and error conditions associated with each API.
Figure 1: The Submit Remote Command Dialog
Figure 2: MsgBox to Display Error Messages
Figure 3: MsgBox, Successful Command Completion
Option Explicit
'declare APPC (router) functions
Declare Function EHNAPPC_IsRouterLoaded Lib "EHNAPPC.DLL" (ByVal hWnd As Integer) As Integer
Declare Function EHNAPPC_QuerySystems Lib "EHNAPPC.DLL" (ByVal hWnd As Integer,
lpSysCount As Integer, ByVal lpSys As String) As Integer
'declare Submit Remote Command functions
Declare Function EHNSR_GetMessage Lib "EHNSRW.DLL" (ByVal hWnd As Integer,
ByVal szSysName As String, lpwSevCode As Integer, ByVal szMsgID As String,
ByVal szMsg As String, ByVal wMsgLen As Integer, ByVal szMsgBuf As String,
ByVal lpwMsgBufLen As Integer) As Integer
Declare Function EHNSR_StopConversation Lib "EHNSRW.DLL" (ByVal hWnd As Integer,
ByVal szSysName As String) As Integer
Declare Function EHNSR_SubmitCommand Lib "EHNSRW.DLL" ( ByVal hWnd As Integer,
ByVal szSysName As String, ByVal szCommand As String, ByVal szMsgBuf As String,
ByVal wMsgBufLen As Integer, ByVal lpProcCallBack As Long) As Integer
'return codes for APPC and Submit Remote Command functions
Global Const EHNAPPC_OK = &H0
Global Const EHNSR_OK = &H0
'global constants for Visual Basic
Global Const MB_OK = 0 'display OK button
Global Const MB_ICONSTOP = 16 'STOP icon
Global Const MB_ICONINFORMATION = 64 'INFORMATION icon
Global Const DEFAULT = 0 'default mouse pointer
Global Const HOURGLASS = 11 'hourglass mouse pointer
Global Const BLUE = &HFF0000 'blue color
Global Const RED = &HFF 'red color
'other global variables and constants
Global gblSystemList As String * 320 'list of systems connected to
Global gblSystemName As String 'system name
Global Const gblMsgBufferLength = 1000 'message buffer length
Global gblMsgBuffer As String * gblMsgBufferLength Sub Form_Load ()
Dim I As Integer 'loop counter
Dim StartPos As Integer 'position in SystemList
Dim SystemCount As Integer 'number of systems connected to
'check for router loaded - MsgBox if not
If EHNAPPC_IsRouterLoaded(hWnd) = False Then
MsgBox "The Client Access/400 Router is not loaded.", MB_OK + MB_ICONSTOP,
"Router Not Loaded"
End
End If
'get list of systems router is connected to, pick out default for combo box
If Not EHNAPPC_OK = EHNAPPC_QuerySystems(hWnd, SystemCount, gblSystemList) Then
MsgBox "Error occurred on QuerySystems API.", MB_OK + MB_ICONSTOP,
"Query Systems Error"
End
End If
'get system names, put in list box
StartPos = 1
For I = 1 To SystemCount
lstSystemName.AddItem Mid$(gblSystemList, StartPos, 8) 'SysName is 8 chars
StartPos = StartPos + 10 'but API returns names of length 10
Next I
lstSystemName.ListIndex = 0 'set default system in list box
cmdShowMessages.Enabled = False 'start with Show Messages disabled
End Sub Sub cmdSubmit_Click ()
Dim APIReturnCode As Integer 'return code
Dim I As Integer 'loop control
'no processing if blank command entered
If txtCommand = "" Then
lblMessageLine = "Blank command not submitted."
lblMessageLine.ForeColor = RED
Exit Sub
End If
'trim all trailing characters after command string (CR, LF, etc.)
For I = 1 To Len(txtCommand)
If Mid(txtCommand, I, 1)
Figure 4: Module RMTCMD.BAS 'message buffer
Figure 5: The Form_Load Subroutine in RMTOMD.FRM
txtCommand = Mid(txtCommand, 1, I -1)
Exit For
End If
Next I
initialize for Submit processing
gblMsgBuffer = Space$(gblMsgBufferLength) clear out buffer
Screen.MousePointer = HOURGLASS set pointer - long wait
APIReturnCode = EHNSR_SubmitCommand(hWnd, gblSystemName, txtCommand,
gblMsgBuffer, gblMsgBufferLength, 0)
Screen.MousePointer = DEFAULT restore mouse
display status message line
If APIReturnCode = EHNSR_OK Then
lblMessageLine = Command submitted sccessfully.
lblMessageLine.ForeColor = BLUE
Else
lblMessageLine = Error on submitted command.
lblMessageLine.ForeColor = RED
End If
enable Show Messages button for message review
cmdShowMessages.Enabled = True
End Sub Sub cmdShowMessages_Click ()
'get/format/show messages from Submit Command API execution
Dim APIReturnCode As Integer 'return code
Dim Msg As String 'AS/400 message
Dim MsgID As String * 8 'AS/400 message ID
Dim MsgLength As Integer 'AS/400 message length
Dim ReturnMsg As String 'formatted return messages
Dim SeverityCode As Integer 'msg severity code
ReturnMsg = "" 'initialize
MsgLength = 100 'length of msg to retrieve
'loop through messages - end when no more messages in reply buffer
Do
Msg = Space$(MsgLength) 'initialize retrieved msg
APIReturnCode = EHNSR_GetMessage(hWnd, gblSystemName, SeverityCode,
MsgID, Msg, MsgLength, gblMsgBuffer, gblMsgBufferLength)
If APIReturnCode EHNSR_OK Then Exit Do 'no more msgs
'remove null terminator from Message ID (length 4 or 7)
If InStr(MsgID, Chr(0)) > 0 Then
MsgID = Mid$(MsgID, 1, InStr(MsgID, Chr(0)) - 1)
'extract message up to null terminator in message
If InStr(Msg, Chr(0)) > 0 Then
Msg = Mid$(Msg, 1, InStr(Msg, Chr(0)) - 1)
'Format MsgBox message for display
ReturnMsg = ReturnMsg & "Message ID: " & MsgID & Chr(10)
ReturnMsg = ReturnMsg & "Message: " & Msg & Chr(10) & Chr(10)
Loop
'display MsgBox with formatted messages
MsgBox ReturnMsg, MB_OK + MB_ICONINFORMATION,
"Messages from Submit Command API"
'disable Show Messages button - can only retrieve once from reply buffer
cmdShowMessages.Enabled = False
End Sub Sub txtCommand_Change ()
'disable Show Messages button - no longer valid for new message
cmdShowMessages.Enabled = False
End Sub Sub cmdExit_Click ()
Dim APIReturnCode As Integer 'return code
Figure 6: The cmdSubmit_Click Subroutine in RMTCMD.FRM
Figure 7: The cmdShowMessages_Click Subroutine in RMTCMD.FRM
Figure 8: The txtCommand_Change Subroutine in RMTCMD.FRM
'call Stop Conversation API to release any conversations
APIReturnCode = EHNSR_StopConversation(hWnd, gblSystemName)
End
End Sub
Figure 9: The cmdExit_Click Subroutine in RMTCMD.FRM
LATEST COMMENTS
MC Press Online