There are two possible ways to monitor user input:
Register the KeyDown
event to monitor what the user is typing.
Plug your code into data transport layer and monitor what data are sent to the remote host. Please note that you will see the encoded data sent by the terminal, which means that you will see escape sequences for function keys. For example, you can see 0x1B 0x5B 0x44
for Left-arrow-key
, 0x1B 0x4F 0x50
for F1-key
, etc.
The second approach has a benefit, you can also monitor the received data.
To plug into data transport layer, make your own IShellChannelFactory
implementation. It can look like this:
public class MyChannelFactory : IShellChannelFactory
{
private IShellChannelFactory _factory;
private Action<byte[], int, int> _dataReceived;
private Action<byte[], int, int> _dataSent;
public MyChannelFactory(IShellChannelFactory factory,
Action<byte[], int, int> dataReceived = null,
Action<byte[], int, int> dataSent = null)
{
_factory = factory ?? throw new ArgumentNullException("factory");
_dataReceived = dataReceived;
_dataSent = dataSent;
}
public ShellChannel CreateShellChannel(TerminalOptions options, int columns, int rows)
{
return new MyChannel(this, _factory.CreateShellChannel(options, columns, rows));
}
private class MyChannel : ShellChannel
{
private MyChannelFactory _owner;
private ShellChannel _channel;
public MyChannel(MyChannelFactory owner, ShellChannel channel)
{
_owner = owner;
_channel = channel;
}
public override int Receive(byte[] buffer, int offset, int count)
{
var n = _channel.Receive(buffer, offset, count);
_owner._dataReceived?.Invoke(buffer, offset, n);
return n;
}
public override int Send(byte[] buffer, int offset, int count)
{
var n = _channel.Send(buffer, offset, count);
_owner._dataSent?.Invoke(buffer, offset, n);
return n;
}
public override ShellChannelOptions Options { get { return _channel.Options; } }
public override int Available { get { return _channel.Available; } }
public override bool Connected { get { return _channel.Connected; } }
public override int TerminalWidth { get { return _channel.TerminalWidth; } }
public override int TerminalHeight { get { return _channel.TerminalHeight; } }
public override void Close() { _channel.Close(); }
public override ShellChannelState GetConnectionState() { return _channel.GetConnectionState(); }
public override PollResult Poll(int microSeconds) { return _channel.Poll(microSeconds); }
public override void SetTerminalSize(int width, int height) { _channel.SetTerminalSize(width, height); }
}
}
And it can be used like this:
var ssh = new Ssh();
ssh.Connect("test.rebex.net");
ssh.Login("demo", "password");
terminal.Bind(new MyChannelFactory(ssh, receivedDataHandle, sentDataHandle);