Class

Shell


Description

Used to execute Unix or DOS Shell commands under Windows, macOS, or Linux.

Methods

Name

Parameters

Returns

Shared

Close

Execute

Command As String, [Parameters As String]

Poll

ReadAll

String

Write

Text As String

WriteLine

Text As String

Events

Name

Parameters

Returns

Completed

DataAvailable

Enumerations

Shell.ExecuteModes

ExecuteModes

Specifies the types of modes in which the Shell can execute.

Enum

Description

Synchronous

(Default) The shell executes its command and returns the result in the Result property when the script has finished running. Synchronous shells block the main UI thread, even when they are in a thread themselves. For long-running shell processes, use one of the other shell modes instead.

Asynchronous

The shell executes its command and returns data via the DataAvailable event. It does not wait for a command to finish before executing the next command. An asynchronous shell script can run in the background. You'll need to make sure the Shell instance does not go out of scope while you are waiting for operations to complete.

Interactive

The script can display a prompt and the user can interact with the shell script while it is running. Data can be sent to a running shell session with the Write method and data is returned via the DataAvailable event. Refer the interactive shell Example included with your installation (Advanced/Shell). You'll need to make sure the Shell instance does not go out of scope while you are waiting for operations to complete.

Property descriptions


Shell.Arguments

Arguments As String

Specifies the arguments to pass to the Shell backend. The default is "-c".


Shell.Backend

Backend As String

Changes the Shell backend that is used. The default is "bash". This property applies only to Linux and macOS.

Change the Shell backend to Bourne Shell (if available):

Var sh As New Shell
sh.Backend = "bourne"
sh.Execute("ls")
TextArea1.Text = sh.Result

Shell.Canonical

Canonical As Boolean

True to allow control characters to be sent to the Shell.

Use this property to support special control characters like Ctrl+A (go to first line), and Ctrl-E (go to last line), etc. which normally just transmit as actual binary data to the Shell.

False (default) means current behavior (i.e. receiving input without the need for a new-line), but if enabled then the Shell will operate in Canonical mode (i.e. waiting on input until a new-line is received which allows these special character to work). The Canonical mode must be set before calling Execute to be effective, just like the Shell.Mode property.


Shell.ExecuteMode

ExecuteMode As ExecuteModes

Controls the mode in which the Shell operates. The Shell can be running in Synchronous, Asynchronous, or Interactive modes.

To access the DataAvailable event handler, you can subclass Shell or use AddHandler.

The following terminal application allows you to submit Unix commands using the interactive mode. The interface consists of two TextFields, InputField, in which the user can enter a command, and OutputField that displays the results.

The Opening event for the window initializes the Shell object (declared as a property of the window).

mShell = New Shell
mShell.ExecuteMode = Shell.ExecuteModes.Interactive

The user can type a unix command into the TextField, InputField. When they press Return, the following code in the TextField's KeyDown event runs. The Write method sends the command to the Shell's input buffer.

If Key = Encodings.UTF8.Chr(13) Then
  If Not mShell.IsRunning Then
    mShell.Execute "sh"
  End If
  mShell.Write(InputField.Text)
  mShell.Write(CEncodings.UTF8.Chr(13))
  InputField.Text = ""
  Return True
Else
  Return False
End If

A Timer calls the ReadAll method in its Action event and displays the output in OutputField:

If mShell <> Nil Then
  Var output As String = mShell.ReadAll
  If output <> "" Then
    OutputField.SelectedText = output
  End If
End If

Shell.ExitCode

ExitCode As Integer

The exit code returned by the Shell.

It returns 0 if the Execute method was executed successfully. Otherwise, it returns a system-supplied exit code. On Windows, it returns -1 if execution fails.

This example checks the value of exit code and prints it if it is not zero.

Var sh As New Shell

sh.Backend = TextField1.Text
sh.Arguments = TextField2.Text
sh.Execute TextField3.Text
TextArea1.Text = sh.Result
If sh.ExitCode <> 0 Then
  MessageBox("The exit code is: " + sh.ExitCode.ToString)
End If

Shell.IsRunning

IsRunning As Boolean

True if an asynchronous or interactive Shell process is running.

This example checks whether the Shell is running before trying to use it.

If sh.IsRunning Then
  sh.Poll
End If

Shell.PID

PID As Integer

The ID of the interactive Shell process.


Shell.Result

Result As String

Contains the contents of the output buffer without clearing the buffer.

This example runs the "ls" command in a Shell and displays the results:

Var sh As New Shell

sh.Execute("ls")
TextArea1.Text = sh.Result

Shell.TimeOut

TimeOut As Integer

The time (in milliseconds) that specifies how long a process can run before it is automatically terminated (Windows only). The default is 2000 or 2 seconds. Use -1 to indicate no timeout.

Timeout is only used on Microsoft Windows.

Var s As New Shell
s.ExecuteMode = Shell.ExecuteModes.Synchronous
s.TimeOut = 10000

s.Execute("DIR")

Select Case s.ExitCode
Case -2
  'the command timed out
Case 0
  'the command succeeded
Else
  'Something else happened
End Select

Method descriptions


Shell.Close

Close

Shuts down the running command. Calling Close triggers the Completed event.

Var sh As New Shell
.
.
sh.Close

Shell.Execute

Execute(Command As String, [Parameters As String])

Executes a one-line Unix or DOS Shell command.

If you are in Synchronous mode (mode 0), the Result property will contain the results. The Command parameter is the path/name of the executable to run and the second parameter contains the arguments to pass to the executable. You can specify the executable without passing a second parameter. On Windows, if the path/name of the executable contains spaces and you want to pass arguments to it, it is safer to separate the two.

If you are in Asynchronous mode (mode 1 or 2), use the Execute method for the first command to be executed. In Interactive mode (mode 2), you can then later use Write or WriteLine to send data or new commands to the Shell.

Execute the "ls" command in a Shell and display the results in a TextArea:

Var sh As New Shell

sh.Execute("ls")
TextArea1.Text = sh.Result

Shell.Poll

Poll

Looks for data returned from the running Shell and may trigger a DataAvailable event.

Var sh As New Shell
.
.
sh.Poll

Shell.ReadAll

ReadAll As String

Returns the contents of the output buffer and clears the buffer. As a consequence, the property Result will return an empty string.


Shell.Write

Write(Text As String)

Sends the passed string to the Shell's input buffer.


Shell.WriteLine

WriteLine(Text As String)

Sends the passed string ending in a linefeed to the Shell's input buffer.

Event descriptions


Shell.Completed

Completed

Called only in modes 1 and 2. Triggered whenever the executed command is finished or the Close method is called.


Shell.DataAvailable

DataAvailable

Occurs when additional data has come into the internal receive buffer.

Notes

Use the Shell class to execute DOS or Unix commands and get the results. The Execute method executes a one-line command in Synchronous mode. This causes two properties of the Shell object to change: ErrorCode, which is a system-supplied error code or 0 for no error; and Result, which is a string containing the output of the command. The TimeOut property specifies how long (in milliseconds) a process can run before it is automatically terminated. A value of -1 means the process can run indefinitely. This property currently applies only to Windows.

The process running in the Shell is killed when the object gets out of scope even if running in asynchronous or interactive modes.

The Shell is not equivalent to the Terminal or Command app for your OS. Paths and other default settings will likely not be the same. If you need to do configuration of the Shell before you use it, be sure to set it up to be interactive so you can set up the configuration before calling other Shell commands. Alternatively you could create a batch file that sets everything up and call that instead.

Warning

If you send a unavailable command to the Shell, a ShellNotAvailableException will be raised.


Shell differences on windows

It appears that some Windows Shell commands such as ftp or telnet will not work as expected due to these tools not using the standard IO streams that can be read by the Shell class.

Some workarounds:

  • Take advantage of the ftp commands built-in scripting capability.

  • Spawn the ftp app in a hidden console window and read its input using low-level console IO functions as described in this Microsoft document: http://msdn.microsoft.com/en-us/library/ms684965(VS.85).aspx

  • Use a 3rd part ftp or telnet class.

Sample code

Using the synchronous mode, the following code lists the current directory's files using the dir command on Windows and ls on macOS and Linux.

Var s As Shell
s = New Shell
#If TargetWindows Then
  s.Execute("dir")
#ElseIf TargetMacOS Or TargetLinux Then
  s.Execute("ls -la")
#Endif
If s.ExitCode = 0 Then
  TextField1.Text= s.Result
Else
  MessageBox("Error code: " + s.ErrorCode.ToString)
End If

The following example gets the names and values of the environment variables on the user's computer and displays the information in a TextField. You can use the EnvironmentVariable method of the System module to get or set individual environment variables.

Var s As New Shell
Var cmd As String
#If TargetMacOS Or TargetLinux Then
  cmd = "env"
#ElseIf TargetWindows Then
  cmd = "set"
#Endif
s.Execute(cmd)
If s.ExitCode = 0 Then
  TextField1.Text = s.Result
Else
  TextField1.Text = "Error " + Str(s.ErrorCode)
End If

The following terminal application allows you to submit Unix commands using the interactive mode. The interface consists of two TextFields, InputField, in which the user can enter a command, and OutputField that displays the results.

The Opening event for the window initializes the Shell object (declared as a property of the window).

mShell = New Shell
mShell.ExecuteMode = Shell.ExecuteModes.Interactive

The user can type a unix command into the TextField, InputField. When he presses Return, the following code in the TextField's KeyDown event runs. The Write method sends the command to the Shell's input buffer.

If key = Chr(13) Then
  If Not mShell.IsRunning Then
    mShell.Execute("sh")
  End If
  mShell.Write(InputField.Text)
  mShell.Write(Chr(13))
  InputField.Text = ""
  Return True
Else
  Return False
End If

A Timer calls the ReadAll method in its Action event and displays the output in OutputField:

If mShell <> Nil Then
  Var output As String = mShell.ReadAll
  If output <> "" Then
    OutputField.SelectedText = output
  End If
End If

Compatibility

All project types on all supported operating systems.

See also

Object parent class; TargetLinux, TargetMachO, TargetMacOS, TargetWindows, TargetX86 constants.