+1 vote
by (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
by (15.2k 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.

...