Rebex SSH Shell
SSH shell, tunneling, telnet, ANSI terminal emulation library for .NET
Download 30-day free trial Buy from $699More .NET libraries
-
Rebex SFTP
SFTP client
-
Rebex SSH Pack
SSH Shell + SFTP + SSH server
-
Rebex Total Pack
All Rebex .NET libraries together
Back to feature list...
Scripting
On this page:
Scripting object
Scripting
object is the core of Rebex Terminal Emulation's powerful scripting API. It's available
in both TerminalControl
and VirtualTerminal
:
// get the scripting object from // a TerminalControl or VirtualTerminal Scripting scripting = terminal.Scripting; // do some scripting // ...
' get the scripting object from ' a TerminalControl or VirtualTerminal Dim scripting As Scripting = terminal.Scripting ' do some scripting ' ...
Alternatively, you can get a stand-alone Scripting
object by calling Ssh.StartScripting
method:
// create an instance of Ssh object var ssh = new Rebex.Net.Ssh(); // connect and log in ssh.Connect(serverName); ssh.Login(username, password); // start a scripting session // and get a stand-alone scripting object Scripting scripting = ssh.StartScripting(); // do some scripting // ...
' create an instance of Ssh object Dim ssh = New Rebex.Net.Ssh() ' connect and log in ssh.Connect(serverName) ssh.Login(username, password) ' start a scripting session ' and get a stand-alone scripting object Dim scripting As Scripting = ssh.StartScripting() ' do some scripting ' ...
Tip: You can get an ITerminal
used by the stand-alone Scripting
object through its Terminal
property.
Automatic prompt detection
In most cases, the first thing you need to do is to make sure the remote system's command prompt can be reliably detected.
DetectPrompt
method detects the prompt automatically in most cases:
// detect the prompt automatically scripting.DetectPrompt();
' detect the prompt automatically scripting.DetectPrompt()
Note: This method should only be called when the remote system is actually showing the prompt and is waiting for input. Calling it while a command has been executed will usually result in a failure (unless the command has a command prompt of its own).
Custom prompts
If automatic prompt detection can't be used, you can specify the remote system's command prompt yourself
using Prompt
property:
// specify the remote prompt scripting.Prompt = "> ";
' specify the remote prompt scripting.Prompt = "> "
The prompt can be specified by a simple text, by text with wildcards or by a regular expression:
-
Simple text - Matches an exact phrase.
If the remote server prompt is the server hostname ending with '#' and a whitespace, the"hostname# "
string can be used to match the prompt.
Note that this type of prompt requires that server prompt to remain constant during the whole session. In practice, prompts of many Unix-based shells contain the current path, making it necessary to use one of the other prompt specification methods. -
Wildcards - Matches a phrase with wildcards.
If the server prompt can vary slightly, it is possible to utilize wildcards to handle prompt changes or variants. This type has to be prefixed with the "mask:" string when being set. Available wildcards:
'?' - matches any one character.
'*' - matches any character sequence including zero length sequence.
Let's say the server's prompt is "username@hostname:currentPath$ " (as in most Unix shells), where currentPath changes during the session and the '$' character can change to '#' if logged as the "root" superuser (administrator).
In this case,"mask:userName@serverName:*? "
string can be used to match the prompt. -
Regular expression - Matches a regular expression.
This is the most versatile prompt expression type. It uses regular expression to match command response endings. This type has to be prefixed with the "regex:" string when being set. Let's say the server's prompt is "username@hostname:currentPath$ " (the same as above), where currentPath changes during the session and the '$' character can change to '#' if logged as the "root" superuser (administrator).
In this case,"regex:(userName[@]serverName[:].*[$])|(serverName[:].*[#])"
string can be used to match the prompt.
Regular expressions are not the topic of this tutorial, but lots of information about them can be found elsewhere.
Executing commands
Once you have detected or specified the remote system's command prompt,
you can easily execute a command by calling the SendCommand
method and read its response with ReadUntilPrompt
method:
// start a command scripting.SendCommand("ls -lR"); // and read its response string response = scripting.ReadUntilPrompt();
' start a command scripting.SendCommand("ls -lR") ' and read its response Dim response As String = scripting.ReadUntilPrompt()
Tip: If you only need to execute one simple command and read its response,
use Ssh.RunCommand
.
Simulating keyboard keys
There are several Send
method overloads that can be used to simulate keyboard input. From the remote terminal's point-of-view, these are indistinguishable
from the actual key presses.
// simulate pressing an 'Escape' key scripting.Send(FunctionKey.Escape); // simulate pressing 'Ctrl+C' scripting.Send(ConsoleKey.C, ConsoleModifiers.Control); // send capital 'X' var key = new ConsoleKeyInfo('X', ConsoleKey.X, true, false, false); scripting.Send(key); // another way to send capital 'X' scripting.Send("X");
' simulate pressing an 'Escape' key scripting.Send(FunctionKey.Escape) ' simulate pressing 'Ctrl+C' scripting.Send(ConsoleKey.C, ConsoleModifiers.Control) ' send capital 'X' Dim key = New ConsoleKeyInfo("X"c, ConsoleKey.X, True, False, False) scripting.Send(key) ' another way to send capital 'X' scripting.Send("X")
Sending data
Use SendCommand
method to send a command or other similarly-behaving text to the server (this includes usernames, passwords, etc.).
In addition to sending the specified text, it also sends a proper end-of-line sequence and receives data from the server until an end-of-line is reached.
// send a command (with enter key, etc.) scripting.SendCommand("some text");
' send a command (with enter key, etc.) scripting.SendCommand("some text")
However, Scripting
also provides several variants of Send
method that are more low-level. They only send the specified text
or simulate the specified key and don't perform any other processing:
// send raw text (and do nothing else) scripting.Send("raw text"); // send an 'Enter' key scripting.Send(FunctionKey.Enter); // send a byte array scripting.SendData(byteArray, 0, byteArray.Length);
' send raw text (and do nothing else) scripting.Send("raw text") ' send an 'Enter' key scripting.Send(FunctionKey.Enter) ' send a byte array scripting.SendData(byteArray, 0, byteArray.Length)
Note: The data-sending methods don't actually require that the Prompt
has been set prior to calling them.
Also, when scripting TerminalControl
, they don't require the processing mode to be changed to non-automatic.
Reading response
There are several methods for receiving response from the server. ReadChar
and ReadLine
are straightforward and don't even require setting Prompt
before calling them:
// receive a single character char c = scripting.ReadChar(); // receive a single line string line = scripting.ReadLine();
' receive a single character Dim c As Char = scripting.ReadChar() ' receive a single line Dim line As String = scripting.ReadLine()
However, when scripting multiple commands over a single shell, ReadUntilPrompt
is usually more useful. As the name suggests,
the Prompt
has to be detected or set before calling it for the first time:
// detect the prompt automatically scripting.DetectPrompt(); // execute a command scripting.SendCommand("echo Hello!"); // receive response until the remote system's // prompt is encountered string response = scripting.ReadUntilPrompt(); // execute another command scripting.SendCommand("hostname"); // receive response for the second command response = scripting.ReadUntilPrompt();
' detect the prompt automatically scripting.DetectPrompt() ' execute a command scripting.SendCommand("echo Hello!") ' receive response until the remote system's ' prompt is encountered Dim response As String = scripting.ReadUntilPrompt() ' execute another command scripting.SendCommand("hostname") ' receive response for the second command response = scripting.ReadUntilPrompt()
If the executed command is more advanced and might result in multiple outcomes, try ReadUntil
method instead.
Tip: If you don't need to 'read' any response and just want the terminal to receive and process whatever data has been sent (and update the contents of the terminal screen),
use Scripting.Process
method.
Advanced response matching
ReadUntil
method receives server response until the specified condition is met. It accepts a wide range of different 'events' and even makes it possible to combine them.
For example, it's easily possible to receive response until one of several events occur:
// receive response until either the remote system's // prompt or the 'Name: ' text is encountered string response = scripting.ReadUntil(ScriptEvent.Prompt, ScriptEvent.FromString("Name: "));
' receive response until either the remote system's ' prompt or the 'Name: ' text is encountered Dim response As String = scripting.ReadUntil(ScriptEvent.Prompt, ScriptEvent.FromString("Name: "))
WaitFor
behaves just like ReadUntil
, but it returns an instance of ScriptMatch
instead of the received response.
This makes it possible to easily determine which of the specified conditions was actually matched:
// receive response until either the remote system's // prompt or the 'Name: ' text is encountered ScriptMatch match = scripting.WaitFor(ScriptEvent.Prompt, ScriptEvent.FromString("Name: ")); // get the response received during the previous method if needed string response = scripting.ReceivedData; // determine what to do depending on whether the prompt was matched if (match.IsPrompt) { // do something } else { // do something else }
' receive response until either the remote system's ' prompt or the 'Name: ' text is encountered Dim match As ScriptMatch = scripting.WaitFor(ScriptEvent.Prompt, ScriptEvent.FromString("Name: ")) ' get the response received during the previous method if needed Dim response As String = scripting.ReceivedData ' determine what to do depending on whether the prompt was matched ' do something If match.IsPrompt Then ' do something else Else End If
ScriptEvent
object is easy-to-use:
// strings get converted to ScriptEvent.FromString(value) match = scripting.WaitFor("Name: "); // supports operators such as 'and' and 'or' match = scripting.WaitFor(event1 & event2); // wait until a non-control character is received or the connection is closed match = scripting.WaitFor(ScriptEvent.AnyText | ScriptEvent.Closed);
' strings get converted to ScriptEvent.FromString(value) match = scripting.WaitFor("Name: ") ' supports operators such as 'and' and 'or' match = scripting.WaitFor(event1 And event2) ' wait until a non-control character is received or the connection is closed match = scripting.WaitFor(ScriptEvent.AnyText Or ScriptEvent.Closed)
Tip: Setting Scripting.AutoMatchPrompt
to true
will make every call to WaitFor
or ReadUntil
automatically include
ScriptEvent.Prompt
.
Tip: See the scripting code for telnet authentication.
Response matching with tags
To determine which of the multiple ScriptEvent
objects was matched in a WaitFor
call, use one of the various ScriptMatch
properties.
If this is still not sufficient to distinguish one 'event' from another, use custom tags:
// receive response until either the remote system // asks for name or password ScriptMatch match = scripting.WaitFor( ScriptEvent.Prompt, ScriptEvent.Closed, ScriptEvent.FromString("Name: ").SetTag("name"), // set custom tag ScriptEvent.FromString("Password: ").SetTag("password") // set custom tag ); if (match.IsClosed) { // exit } else if (match.IsPrompt) { // send another command } else { // get match info for an event with tag of "name" ScriptMatchInfo info = match.GetMatchInfoByTag("name"); if (info != null) { // send the name } else { // get match info for an event with tag of "password" info = match.GetMatchInfoByTag("password"); if (info != null) { // send the password } else { // fail } } }
' receive response until either the remote system ' asks for name or password Dim match As ScriptMatch = scripting.WaitFor( ScriptEvent.Prompt, ScriptEvent.Closed, ScriptEvent.FromString("Name: ").SetTag("name"), ScriptEvent.FromString("Password: ").SetTag("password")) If match.IsClosed Then ' exit ElseIf match.IsPrompt Then ' send another command Else ' get match info for an event with tag of "name" Dim info As ScriptMatchInfo = match.GetMatchInfoByTag("name") If info IsNot Nothing Then ' send the name Else ' get match info for an event with tag of "password" info = match.GetMatchInfoByTag("password") If info IsNot Nothing Then ' send the password Else ' fail End If End If End If
Many supported events
WaitFor
, ReadUntil
and CheckFor
methods accept one or more ScriptEvent
objects.
The following table lists all the supported event types:
Event | Description |
---|---|
And (event1, event2) | Both of the conditions must be met. |
AnyText | Matches any character that is not part of an escape sequence (for example color change is not matched). |
Closed | Matches closed communication channel. |
CursorAtPosition (row, column) | Matches a cursor appearing at the specified position. |
CursorInArea (row, column, width, height) | Matches a cursor appearing in the specified area. |
Delay (milliseconds) | Matches a delay (no data arrived for the specified time span). |
Duration (miliseconds) | Matches time spent on receiving and processing data. |
FromRegex (pattern) | Matches the regular expression. |
FromString (text) | Matches the specified string. |
Line | Matches an end-of-line ('\n') sequence. |
Not (event1) | A condition must not be met. |
Or (event1, event2) | At least one of the conditions must be met. |
Prompt | Matches the prompt specified by Prompt property. |
TextAtPosition (text, row, column) | Matches the specified string appearing at the specified position. |
TextInRegion (text, row, column, width, height) | Matches the specified string appearing inside the specified region. |
TextOnCursorLine (text) | Matches the specified string appearing at the cursor line. |
TextOnScreen (text) | Matches the specified string appearing anywhere on the screen |
Timeout | Matches timed-out operation. |
Remote exec
When using SSH, it's possible to start scripting by launching a remote command instead of a shell. When the command ends, the scripting session ends as well. This is very useful if you need to ensure that the remote command won't suddenly fail and get back to shell without notice.
// create an instance of Ssh object var ssh = new Rebex.Net.Ssh(); // connect and log in ssh.Connect(serverName); ssh.Login(username, password); // start command-line FTP client on a remote server Scripting scripting = ssh.StartScripting("ftp test.rebex.net"); // do some FTP client scripting // ...
' create an instance of Ssh object Dim ssh = New Rebex.Net.Ssh() ' connect and log in ssh.Connect(serverName) ssh.Login(username, password) ' start command-line FTP client on a remote server Dim scripting As Scripting = ssh.StartScripting("ftp test.rebex.net") ' do some FTP client scripting ' ...
Note: To launch a remote command instead of shell when binding a
TerminalControl
or VirtualTerminal
object to Ssh
, set terminal's Options.RemoteCommand
to the desired remote command before binding.
Keep-alive packet
Use Scripting.KeepAlive
method to prevent your session from timing out when there is no user interaction for a long time.
This method sends a single keep-alive packet (SSH_MSG_IGNORE for SSH and NOOP for Telnet) to the server. To prevent the session from timing out,
call it every minute or so.
Note: When using SSH transport layer, consider calling
SshSession.KeepAlive
instead.
Back to feature list...