3

I'm currently working on a terminal emulation using SSH.NET. Creating a SshClient and a ShellStream with current columns/rows work properly.

But when I change the size of the terminal dimensions (like Putty) I can't find a way to send the new colums/rows to the server.

The only way I see is to close the shellstream and create a new one. Is there a better way to send the new "layout" to the server?

Thanks in advance :-)

2 Answers 2

2

After days of investigation I ended up in implementing a new method into ShellStream.cs:

    /// <summary>
    /// Sends a "window-change" request.
    /// </summary>
    /// <param name="columns">The terminal width in columns.</param>
    /// <param name="rows">The terminal width in rows.</param>
    /// <param name="width">The terminal height in pixels.</param>
    /// <param name="height">The terminal height in pixels.</param>
    public void SendWindowChangeRequest(uint columns, uint rows, uint width, uint height)
    {
        if (_channel == null)
        {
            throw new ObjectDisposedException("ShellStream");
        }
        _channel.SendWindowChangeRequest(columns, rows, width, height);
    }

That solved the problem. Now I can call "SendWindowChangeRequest(...)" and the server-side shell window is up to date :-)

Not sure, why this feature is missing in Renci's implementation. Maybe there is still another way...

Sign up to request clarification or add additional context in comments.

1 Comment

I ended up getting the _channel private by reflection and then invoking the method on it.
1

To solve the problem, I created an extension method that via reflection succeeds in calling the SendWindowChangeRequest method of the internal ChannelSession class (ShellStream have a private property called _channel).

using System.Reflection;
using Renci.SshNet;

namespace YourFavNamespace;

public static class ShellStreamExtension
{
    public static void SendWindowChangeRequest(this ShellStream stream, uint cols, uint rows, uint width, uint height)
    {
        // The shell stream is a private class, so we need
        // to use reflection to access its private fields and methods
        // The strategy is to get the _channel field from the ShellStream, and then
        // get the SendWindowChangeRequest method from the _channel field
        // for submitting low level requests to the shell stream to change its window size at runtime
        
        // get _channel from ShellStream by reflection
        var _channel = 
            stream.GetType().GetField("_channel", 
                BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(stream);
        
        // get SendWindowChangeRequest method from _channel by reflection
        var method = 
            _channel?.GetType().GetMethod("SendWindowChangeRequest", 
                BindingFlags.Public | BindingFlags.Instance);
        
        // invoke SendWindowChangeRequest method for change cols, rows, width and height of the shell stream
        method?.Invoke(_channel, new object[] { cols, rows, width, height });
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.