diff --git a/mRemoteNG/Connection/ConnectionInfo.cs b/mRemoteNG/Connection/ConnectionInfo.cs index 095fc473..147e50b9 100644 --- a/mRemoteNG/Connection/ConnectionInfo.cs +++ b/mRemoteNG/Connection/ConnectionInfo.cs @@ -8,6 +8,7 @@ using mRemoteNG.Connection.Protocol; using mRemoteNG.Connection.Protocol.ARD; using mRemoteNG.Connection.Protocol.Http; using mRemoteNG.Connection.Protocol.PowerShell; +using mRemoteNG.Connection.Protocol.Terminal; using mRemoteNG.Connection.Protocol.RAW; using mRemoteNG.Connection.Protocol.RDP; using mRemoteNG.Connection.Protocol.Rlogin; @@ -275,6 +276,8 @@ namespace mRemoteNG.Connection return (int)ProtocolPowerShell.Defaults.Port; case ProtocolType.WSL: return (int)ProtocolWSL.Defaults.Port; + case ProtocolType.Terminal: + return (int)ProtocolTerminal.Defaults.Port; case ProtocolType.IntApp: return (int)IntegratedProgram.Defaults.Port; } diff --git a/mRemoteNG/Connection/Protocol/ProtocolFactory.cs b/mRemoteNG/Connection/Protocol/ProtocolFactory.cs index 42017f56..110a4b5d 100644 --- a/mRemoteNG/Connection/Protocol/ProtocolFactory.cs +++ b/mRemoteNG/Connection/Protocol/ProtocolFactory.cs @@ -9,6 +9,7 @@ using mRemoteNG.Connection.Protocol.ARD; using System; using mRemoteNG.Connection.Protocol.PowerShell; using mRemoteNG.Connection.Protocol.WSL; +using mRemoteNG.Connection.Protocol.Terminal; using mRemoteNG.Resources.Language; using System.Runtime.Versioning; @@ -50,6 +51,8 @@ namespace mRemoteNG.Connection.Protocol return new ProtocolPowerShell(connectionInfo); case ProtocolType.WSL: return new ProtocolWSL(connectionInfo); + case ProtocolType.Terminal: + return new ProtocolTerminal(connectionInfo); case ProtocolType.IntApp: if (connectionInfo.ExtApp == "") { diff --git a/mRemoteNG/Connection/Protocol/ProtocolType.cs b/mRemoteNG/Connection/Protocol/ProtocolType.cs index b9a32a8f..20af662b 100644 --- a/mRemoteNG/Connection/Protocol/ProtocolType.cs +++ b/mRemoteNG/Connection/Protocol/ProtocolType.cs @@ -40,6 +40,8 @@ namespace mRemoteNG.Connection.Protocol [LocalizedAttributes.LocalizedDescription(nameof(Language.Wsl))] WSL = 12, + [LocalizedAttributes.LocalizedDescription(nameof(Language.Terminal))] + Terminal = 12, [LocalizedAttributes.LocalizedDescription(nameof(Language.ExternalTool))] IntApp = 20 @@ -50,6 +52,7 @@ namespace mRemoteNG.Connection.Protocol public static bool SupportBlankHostname(ProtocolType protocolType) { return (protocolType == ProtocolType.IntApp || protocolType == ProtocolType.PowerShell || protocolType == ProtocolType.WSL); + return (protocolType == ProtocolType.IntApp || protocolType == ProtocolType.PowerShell || protocolType == ProtocolType.Terminal); } } } \ No newline at end of file diff --git a/mRemoteNG/Connection/Protocol/Terminal/Connection.Protocol.Terminal.cs b/mRemoteNG/Connection/Protocol/Terminal/Connection.Protocol.Terminal.cs new file mode 100644 index 00000000..4116975a --- /dev/null +++ b/mRemoteNG/Connection/Protocol/Terminal/Connection.Protocol.Terminal.cs @@ -0,0 +1,155 @@ +using System; +using System.Drawing; +using System.Runtime.Versioning; +using System.Windows.Forms; +using mRemoteNG.App; +using mRemoteNG.Messages; +using mRemoteNG.Resources.Language; + +namespace mRemoteNG.Connection.Protocol.Terminal +{ + [SupportedOSPlatform("windows")] + public class ProtocolTerminal(ConnectionInfo connectionInfo) : ProtocolBase + { + #region Private Fields + + private IntPtr _handle; + private readonly ConnectionInfo _connectionInfo = connectionInfo; + private ConsoleControl.ConsoleControl _consoleControl; + + #endregion + + #region Public Methods + + public override bool Connect() + { + try + { + Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, "Attempting to start Terminal session.", true); + + _consoleControl = new ConsoleControl.ConsoleControl + { + Dock = DockStyle.Fill, + BackColor = ColorTranslator.FromHtml("#012456"), + ForeColor = Color.White, + IsInputEnabled = true, + Padding = new Padding(0, 20, 0, 0) + }; + + // Path to command prompt - dynamically determined from system + // Using COMSPEC environment variable which points to the system's command processor + string terminalExe = Environment.GetEnvironmentVariable("COMSPEC") ?? @"C:\Windows\System32\cmd.exe"; + + // Setup arguments based on whether hostname is provided + string arguments = ""; + string hostname = _connectionInfo.Hostname.Trim().ToLower(); + bool useLocalHost = hostname == "" || hostname.Equals("localhost"); + + if (!useLocalHost) + { + // If hostname is provided, try to connect via SSH + // Note: Domain field is not used for SSH as it's Windows-specific + // SSH authentication will use standard SSH mechanisms (password prompt, keys, etc.) + string username = _connectionInfo.Username; + int port = _connectionInfo.Port; + + // Build SSH command + string sshCommand = "ssh"; + + // Add port if it's not the default SSH port (22) + if (port > 0 && port != 22) + { + sshCommand += $" -p {port}"; + } + + if (!string.IsNullOrEmpty(username)) + { + sshCommand += $" {username}@{_connectionInfo.Hostname}"; + } + else + { + sshCommand += $" {_connectionInfo.Hostname}"; + } + + arguments = $"/K {sshCommand}"; + } + else + { + // For local sessions, just start cmd with /K to keep it open + arguments = "/K"; + } + + _consoleControl.StartProcess(terminalExe, arguments); + + // Wait for the console control to create its handle + int maxWaitMs = 5000; // 5 seconds timeout + long startTicks = Environment.TickCount64; + while (!_consoleControl.IsHandleCreated && + Environment.TickCount64 < startTicks + maxWaitMs) + { + System.Threading.Thread.Sleep(50); + } + + if (!_consoleControl.IsHandleCreated) + { + throw new Exception("Failed to initialize terminal console within 5 seconds. This may indicate system resource constraints or permission issues."); + } + + _handle = _consoleControl.Handle; + NativeMethods.SetParent(_handle, InterfaceControl.Handle); + + Resize(this, new EventArgs()); + base.Connect(); + return true; + } + catch (Exception ex) + { + Runtime.MessageCollector?.AddExceptionMessage(Language.ConnectionFailed, ex); + return false; + } + } + + public override void Focus() + { + try + { + NativeMethods.SetForegroundWindow(_handle); + } + catch (Exception ex) + { + Runtime.MessageCollector.AddExceptionMessage(Language.IntAppFocusFailed, ex); + } + } + + protected override void Resize(object sender, EventArgs e) + { + try + { + if (InterfaceControl.Size == Size.Empty) return; + // Use ClientRectangle to account for padding (for connection frame color) + Rectangle clientRect = InterfaceControl.ClientRectangle; + NativeMethods.MoveWindow(_handle, + clientRect.X - SystemInformation.FrameBorderSize.Width, + clientRect.Y - (SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height), + clientRect.Width + SystemInformation.FrameBorderSize.Width * 2, + clientRect.Height + SystemInformation.CaptionHeight + + SystemInformation.FrameBorderSize.Height * 2, true); + } + catch (Exception ex) + { + Runtime.MessageCollector.AddExceptionMessage(Language.IntAppResizeFailed, ex); + } + } + + #endregion + + #region Enumerations + + public enum Defaults + { + Port = 22 + } + + #endregion + } +} diff --git a/mRemoteNG/Language/Language.fr.resx b/mRemoteNG/Language/Language.fr.resx index b6d30075..92609590 100644 --- a/mRemoteNG/Language/Language.fr.resx +++ b/mRemoteNG/Language/Language.fr.resx @@ -2105,6 +2105,9 @@ Le canal nightly inclut les versions alpha, beta et release candidates. PowerShell + + Terminal + Historique des modifications diff --git a/mRemoteNG/Language/Language.pl.resx b/mRemoteNG/Language/Language.pl.resx index d35c8940..b48f4b45 100644 --- a/mRemoteNG/Language/Language.pl.resx +++ b/mRemoteNG/Language/Language.pl.resx @@ -2152,6 +2152,9 @@ Kanał nocny obejmuje wersje alfa, beta i RC (gotowe do wydania). PowerShell + + Terminal + Dziennik zmian diff --git a/mRemoteNG/Language/Language.resx b/mRemoteNG/Language/Language.resx index 5bbe26b2..83b9c5c7 100644 --- a/mRemoteNG/Language/Language.resx +++ b/mRemoteNG/Language/Language.resx @@ -2194,6 +2194,9 @@ Nightly Channel includes Alphas, Betas & Release Candidates. PowerShell + + Terminal + Changelog diff --git a/mRemoteNG/Language/Language.ta.resx b/mRemoteNG/Language/Language.ta.resx index f213fc51..b6b7befb 100644 --- a/mRemoteNG/Language/Language.ta.resx +++ b/mRemoteNG/Language/Language.ta.resx @@ -2155,6 +2155,9 @@ ஆற்றல்ஓடு + + Terminal + மாற்றபதிவு diff --git a/mRemoteNG/Language/Language.zh-CN.resx b/mRemoteNG/Language/Language.zh-CN.resx index be5715ab..5d23e814 100644 --- a/mRemoteNG/Language/Language.zh-CN.resx +++ b/mRemoteNG/Language/Language.zh-CN.resx @@ -2074,6 +2074,9 @@ mRemoteNG 将退出并安装更新。 PowerShell + + Terminal + 网关