Scripting ReadUntil() method

+1 vote
asked Aug 17, 2016 by mertercan83 (220 points)

Hi , i used ReadUntil() method, first call the method is works fine but the second call ReadUntil() method wait a minute and throw exception "Response reading timed out" . Where is the wrong my code?

            var scripting = ssh.StartScripting();

            scripting.Timeout = 60000;

            scripting.DetectPrompt();

            string password = "password";

            ScriptMatch result;
            do
            {
                Console.Write("Enter shell command: ");
                string line1 = null;
                string command = Console.ReadLine();

                scripting.SendCommand(command);
                scripting.WaitFor(ScriptEvent.Duration(3000),ScriptEvent.Prompt);
                string res = scripting.ReceivedData;

                if (res.Contains("password for"))
                {
                    scripting.Send(password + "\n\r");
                    scripting.ReadLine();
                }
                do
                {

                    // read until a line is received (or prompt, or the connection is closed)
                    if(scripting.HoldReceivedData)
                    line1 = scripting.ReadUntilPrompt();

                    // get the result of the ReadUntil method
                    result = scripting.LastResult;

                    // display the line
                    Console.WriteLine(line);

                } while (result.IsLine);

            } while (!result.IsClosed);

1 Answer

+1 vote
answered Aug 17, 2016 by Pavel Matyska (9,720 points)

Hi,

the problem in your code is that you are reading much more than sending commands. You attempted to read when all is already read. I modified your code a little to make it working for me with some limitations I will describe later:

string password = PASSWORD;
var scripting = ssh.StartScripting();           
// set timeout to 1 minute
scripting.Timeout = 60000;
scripting.DetectPrompt();

ScriptMatch result;

do
{
    Console.Write("Enter shell command: ");
    string line1 = null;
    string command = Console.ReadLine();
    bool readingFirstLine = true;

    scripting.SendCommand(command);

    do
    {
        if (readingFirstLine)
        {
            // receive data until:
            // promp is received,
            // or password or Password is received,
            // or new line is received,
            // or the connection is closed (i.e. command was "exit")
            string res = scripting.ReadUntil(ScriptEvent.Prompt, 
                "password for", "Password for", 
                ScriptEvent.Line, ScriptEvent.Closed);
            // get the result of the ReadUntil method
            result = scripting.LastResult;

            Console.Write(res);
            if (result.IsEventMatched("password") || 
                result.IsEventMatched("Password"))
            {
                scripting.Send(PASSWORD + "\r\n");
                Console.WriteLine(scripting.ReadLine());

                // Prompt can change here (i.e. su otheruser) 
                // making ReadUntil(ScriptEvent.Prompt) unusable
                // before specifying new promtp. 
                // Callind DetectPrompt will receive all 
                // response before it can determine new 
                // prompt so it is also unusable in this situation.
            }
            else if (result.IsPrompt || result.IsClosed)
            {
                break;
            }
            readingFirstLine = false;
        }

        // read until a line is received 
        // or prompt, or the connection is closed
        line1 = scripting.ReadUntil(ScriptEvent.Line, 
            ScriptEvent.Prompt, ScriptEvent.Closed);

        // display the line
        Console.WriteLine(line1);

        // get the result of the ReadUntil method
        result = scripting.LastResult;
    } while (result.IsLine);

    readingFirstLine = true;

} while (!result.IsClosed);

It is still far from perfect, since the command can change a prompt (i.e. "cd ..") and ReadingUntil(ScriptEvent.Prompt) cannot be used until the scripting object knows a new prompt. Additionally, when you know that the particular command changes a prompt (i.e. "su otheruser") and also have something on the ouptut, you cannot use DetectPrompt method since it receive all the data before it tries to detect a prompt.

...