Function RunShell() Foundation

Starts a command shell or executes a program.

Syntax
RunShell( <cCmdLine>    , ;
         [<cProgram>]   , ;
         [<lAsync>]     , ;
         [<lBackground>],
         [<aStdHandles>|<lInherit>] ) --> xReturn
Parameters
<cCmdLine>
<cCmdLine> is a character string containing the parameter for the command line of the newly started command shell.
<cProgram>
<cProgram> is a character string which must contain the complete program name (including file extension) for the program executed in the new command environment. The command shell defined by the environment variable OS2_SHELL (OS/2) or COMSPEC (Windows) is used as the default. When this environment variable is not defined, the default value is "CMD.EXE" (OS/2, Windows NT) or "COMMAND.COM" (Windows 9x/Me).
<lAsync>
<lAsync> is a logical value which determines whether the newly started command shell is run synchronously or asynchronously with the Xbase++ application. The default value is .F. (false), meaning that if <lAsync> is not specified, the Xbase++ application is stopped until the new command shell or the newly started program is finished.
<lBackGround>
<lBackGround> is a logical value which determines whether the new command shell is started in the background or foreground. The default value is .F. (false) which means that by default a new process is started in the foreground.
<aStdHandles>
The optional parameter <aStdHandles> is an array with three elements which define the standard input, output and error devices of the new process. The value of each array element can either be NIL, or it can be a numeric file handle. The devices must be specified in the following order:
{nHInput, nHOutput, nHError} 
In case the parameter <aStdHandle> is passed, then the new process also inherits all inheritable handles from the calling process. This behaviour is equivalent to assigning the value .T. (true) to the <lInherit> parameter.
<lInherit>
If the parameter <lInherit> is true (.T.) then the new process inherits all inheritable handles from the calling process. The default value for this parameter is .F. (false), which means that no handles are inherited by the new process.
Return

The return value of RunShell() is the return value of the started command shell or program. When a command shell/program is started in asynchronous mode, the return value is always zero. If RunShell() was not able to start <cProgram>, -1 is returned.

Description

The function RunShell() starts a new command shell and passes a character string to it which is executed on the command line. Normally a new window is opened by RunShell() in which the command defined by <cCmdLine> is executed.

At least the parameter <cCmdLine> must be passed to the function RunShell(). At the minimum this can be a null string (""). In this case RunShell() starts the command shell defined as the default command shell in the environment variable OS2_SHELL (OS/2) or COMSPEC (Windows). If <cCmdLine> contains a null string and no command shell can be started, a runtime error occurs.

The parameter <lAsync> determines whether an Xbase++ application is dependent or independent of the newly started command shell or program. When <lAsync> has the logical value .T. (true), the new program is started and the Xbase++ application continues running independent of it. If the value is .F. (false), the Xbase++ application pauses until the newly started program terminates.

The parameter <lBackGround> determines whether the new process is started in the background or in the foreground of the Xbase++ application. By default RunShell() starts new processes in the foreground, meaning they receive input focus and the applicable window is brought to the foreground. If a "Full-Screen" session is started with RunShell(), the function switches automatically to character mode. If the logical value .T. (true) is specified for <lBackGround>, the new process starts in the background of the Xbase++ application which keeps the input focus.

Processes started using RunShell() normally execute completely independent and cannot access resources allocated in the calling process. This behaviour can be overriden via the <aStdHandles> and <lInherit> parameters. If .T. (true) is passed in <lInherit>, the newly started process inherits all inheritable handles from the parent process. These handles correspond to existing operating system objects such as file handles, named pipes or semaphore objects, which have been marked as inheritable. Similarly, the <aStdHandles> parameter can be used to define existing files as the standard I/O devices to be used by the process spawned by RunShell(). This is often used to redirect the output of the process to a file and is demonstrated in an example below.

With Xbase++ 1.9 and earlier versions the new process inherited all inheritable handles by default. This behaviour has been changed starting with Xbase++ 2.0. In order to achieve the former behaviour, the parameter <lInherit> must be set to .T. (true).

For flexible use of RunShell(), a complete knowledge of the command START and the commands for the command shell is required. Detailed information is available in the online help which can be called on the command line as follows:

VIEW Cmdref Start and VIEW Cmdref Cmd

HELP Cmd and START /?

HELP Command and START /?

Examples
Calling RunShell()

// The example demonstrates various calls of RunShell(). 
// Pay attention to "/C" for passing parameters to a newly started 
// command shell. 

PROCEDURE Main 

   // Open a new DOS session with window title 
   ? RunShell( '/C START "Xbase++ DOS Session"' ) 


   // List current directory to file 
   ? RunShell( "/C DIR /f > dir.txt" ) 


   // Direct call of the Windows program NOTEPAD.EXE including 
   // command line parameter. Asynchronous execution (.T.) 
   // Note: Notepad.exe can be found using PATH. 
   ? RunShell( "dir.txt", "NOTEPAD.EXE", .T. ) 


   // Indirect call of the Windows program EXPLORER.EXE 
   // using the START command. 
   // The explorer displays the current directory 

   ? RunShell( "/C START EXPLORER.EXE ." ) 

   // Direct call of the Windows program Wordpad and passing the name of 
   // an existing document 
   // Note: Wordpad.exe must have the full path included, and the program 
   // name must not be quoted. Codepage specific characters must be converted 
   // to their original code if necessary (ConvToAnsiCp()). 
   ? RunShell( "hello.doc", "C:\Program Files\Windows NT\Accessories\Wordpad.exe" ) 

   // Call Wordpad and passing command line parameters that must be quoted. 
   ? RunShell( '"C:\My Files\hello.doc"', "C:\Program Files\Windows NT\Accessories\Wordpad.exe" ) 

RETURN 
Set the standard devices using RunShell()

// The example demonstrates how files created by the 
// parent process can be set as the standard output 
// devices of a process started with RunShell(). 
// After the new process has exited, the redirected 
// output could be analyzed by processing the 
// file contents on disk. 

#include "fileio.ch" 

#define CRLF Chr(13)+Chr(10) 

#define STDOUT_FILE "stdout.txt" 
#define STDERR_FILE "stderr.txt" 

// 
// The application assumes the roles of both 
// the parent and the child process depending 
// on whether a parameter is passed. 
// 
PROCEDURE Main() 
   IF PCount() == 0 
     ParentProcessMain() 
   ELSE 
     ChildProcessMain() 
   ENDIF 
RETURN 

PROCEDURE ParentProcessMain() 
   LOCAL nHStdOut, nHStdErr, aStdHandles 
   LOCAL nAttribute 

   // The files we are creating will be read/write and 
   // deleted after the file handle is closed. The file 
   // handles can be inherited by the new process. 
   nAttribute := FC_NORMAL+FC_AUTODELETE+FA_INHERITABLE 

   nHStdOut := FCreate( STDOUT_FILE, nAttribute ) 
   nHStdErr := FCreate( STDERR_FILE, nAttribute ) 

   // The files created become the standard output 
   // devices of the new process 
   aStdHandles := {NIL,nHStdOut,nHStdErr} 

   // Start the same application again with a parameter. 
   // Start RunShell() so that it does not return until 
   // the child process is terminated. 
   RunShell( "param", AppName(.F.), .F., ,aStdHandles ) 

   // Print what the child process has written to the 
   // output devices 
   ? "Print nHStdOut" 
   PrintFile( nHStdOut ) 
   ? "Print nHStdErr" 
   PrintFile( nHStdErr ) 

   // Close and delete the files 
   FClose( nHStdOut ) 
   FClose( nHStdErr ) 

RETURN 

// The child process prints to the standard output 
// and standard error device. 
PROCEDURE ChildProcessMain() 
   OutStd( "Output to STDOUT" ) 
   OutErr( "Output to STDERR" ) 
RETURN 

// Print the contents of a file 
PROCEDURE PrintFile( nH ) 
   LOCAL cBuffer 
   FSeek( nH, 0, FS_SET ) 
   cBuffer := Space( FSize( nH ) ) 
   FRead( nH, @cBuffer, Len(cBuffer) ) 
   ? cBuffer 
RETURN 
Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.