0 votes
by (120 points)
edited

Hi.

Trying to use the rebex telnet library to configure a Linux based router programmatically in c# via the router's telnet interface. My code is based largely on the example documented here:

http://www.rebex.net/support/tutorial/telnet/default.aspx#custom-authentication

Code:

        Telnet client = new Telnet("192.168.88.2");
        Shell shell = client.StartShell();
        shell.Prompt = String.Format("mask:[user@server] *> ");

        string prompt = shell.ReadAll("ogin: ");
        shell.SendCommand("admin");
        prompt = shell.ReadAll("sword: ");
        shell.SendCommand("", true);
        prompt = shell.ReadAll();

        // exception on the next line
        shell.SendCommand("interface");
        prompt = shell.ReadAll();

        shell.Close();

Login is successful, but when I attempt to send my first command it throws an exception:

Rebex.TerminalEmulation.TerminalException was unhandled
  HResult=-2146233088
  Message=Unable to process command.
  Source=Rebex.Terminal
  StackTrace:
       at Rebex.TerminalEmulation.Shell.SendCommand(String command, Boolean password)
       at Rebex.TerminalEmulation.Shell.SendCommand(String command)
       at telnetlibtestapp.Form1.button1_Click(Object sender, EventArgs e) in c:\Users\RIME\Documents\Visual Studio 2012\Projects\telnetlibtestapp\telnetlibtestapp\Form1.cs:line 37
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at telnetlibtestapp.Program.Main() in c:\Users\RIME\Documents\Visual Studio 2012\Projects\telnetlibtestapp\telnetlibtestapp\Program.cs:line 19
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

I have tried several different commands, all throw the same exception. The odd thing is that I use shell.SendCommand() during the login process. What am I missing?

Thanks in advance.

3 Answers

0 votes
by (72.7k points)
edited

This kind of exception typically occurs when server's shell is not straight enough. I will try to explain it:

When you send a command e.g. "echo X", straight shell reply is "echo X\r\nX\r\n<prompt>".

When you call shell.SendCommand("echo X") it sends "echo X\r" to the server, then receives the reply above and removes initial "echo X\r\n" from it (we don't want to present command itself in its output). When you then call shell.ReadAll() it takes remaining string "X\r\n<prompt>", removes "<prompt>" from it and returns the result "X\r\n" which is expected command output.

But there is no standard for shells. Because it is primary used for user interaction (not for automatic processing) shell reply can look like this: "\r\e[K<prompt>echo X\r\nX\r\n<prompt>". This has visually same effect, but it is a nightmare for programmer to handle it.

You can use client.LogWriter property to create a Verbose log and see how the response of your server looks.

There are two solutions for this error:

1) Use our experimental class VirtualShell instead of the Shell. It can be used as follows:

VirtualShell shell = new VirtualShell(client.StartVirtualTerminal());

It doesn't use the command extraction specified above (it simply removes everything up to the first '\n', but you are free to implement it yourself). Also please note it uses regex for prompt and arguments of other methods.

2) Send us the produced log file to support@rebex.net and we will try to add support for your kind of shell.

by (120 points)
edited

Thanks, Lukas. I'll do both.

by (72.7k points)
edited

Just for other users viewing this post: my suspicion was correct. The server's shell is not straight enough.

Based on the received log file (thank you for it), I have added support for this kind of shell. It will be included in the next public release.

0 votes
by (72.7k points)
edited

This is fixed in version 2013 R1 (build number 4959).

0 votes
by (15.2k points)
edited

Hi, we have just release new Scripting API in 2014-R2 release. You can read more of its features on Scripting features page.

...