Class
Shell
Description
Used to execute Unix or DOS Shell commands under Windows, macOS or Linux.
Properties
Name |
Type |
Read-Only |
Shared |
---|---|---|---|
Events
Name |
Parameters |
Returns |
---|---|---|
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 = EndOfLine.CR Then
If Not mShell.IsRunning Then
mShell.Execute "sh"
End If
mShell.Write(InputField.Text)
mShell.Write(EndOfLine.CR)
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 Not output.IsEmpty 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.
On Windows, this is the process handle rather than the ID of the 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 = EndOfLine.CR Then
If Not mShell.IsRunning Then
mShell.Execute("sh")
End If
mShell.Write(InputField.Text)
mShell.Write(EndOfLine.CR)
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 Not output.IsEmpty 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.