mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Merge pull request #2954 from mRemoteNG/copilot/add-wsl-connection-protocol
Add WSL protocol support with installation check
This commit is contained in:
@@ -295,7 +295,7 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory(nameof(Language.Connection), 2),
|
||||
LocalizedAttributes.LocalizedDisplayName(nameof(Language.Domain)),
|
||||
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionDomain)),
|
||||
AttributeUsedInProtocol(ProtocolType.RDP, ProtocolType.IntApp, ProtocolType.PowerShell)]
|
||||
AttributeUsedInProtocol(ProtocolType.RDP, ProtocolType.IntApp, ProtocolType.PowerShell, ProtocolType.WSL)]
|
||||
public string Domain
|
||||
{
|
||||
get => GetPropertyValue("Domain", _domain).Trim();
|
||||
|
||||
@@ -274,6 +274,8 @@ namespace mRemoteNG.Connection
|
||||
return (int)ProtocolHTTPS.Defaults.Port;
|
||||
case ProtocolType.PowerShell:
|
||||
return (int)ProtocolPowerShell.Defaults.Port;
|
||||
case ProtocolType.WSL:
|
||||
return (int)ProtocolWSL.Defaults.Port;
|
||||
case ProtocolType.Terminal:
|
||||
return (int)ProtocolTerminal.Defaults.Port;
|
||||
case ProtocolType.IntApp:
|
||||
|
||||
@@ -8,6 +8,7 @@ using mRemoteNG.Connection.Protocol.VNC;
|
||||
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;
|
||||
@@ -48,6 +49,8 @@ namespace mRemoteNG.Connection.Protocol
|
||||
return new ProtocolHTTPS(connectionInfo.RenderingEngine);
|
||||
case ProtocolType.PowerShell:
|
||||
return new ProtocolPowerShell(connectionInfo);
|
||||
case ProtocolType.WSL:
|
||||
return new ProtocolWSL(connectionInfo);
|
||||
case ProtocolType.Terminal:
|
||||
return new ProtocolTerminal(connectionInfo);
|
||||
case ProtocolType.IntApp:
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace mRemoteNG.Connection.Protocol
|
||||
[LocalizedAttributes.LocalizedDescription(nameof(Language.Ard))]
|
||||
ARD = 11,
|
||||
|
||||
[LocalizedAttributes.LocalizedDescription(nameof(Language.Wsl))]
|
||||
WSL = 12,
|
||||
[LocalizedAttributes.LocalizedDescription(nameof(Language.Terminal))]
|
||||
Terminal = 12,
|
||||
|
||||
@@ -49,6 +51,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);
|
||||
}
|
||||
}
|
||||
|
||||
160
mRemoteNG/Connection/Protocol/WSL/Connection.Protocol.WSL.cs
Normal file
160
mRemoteNG/Connection/Protocol/WSL/Connection.Protocol.WSL.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Resources.Language;
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol.WSL
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class ProtocolWSL(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
|
||||
{
|
||||
// Check if WSL is installed
|
||||
if (!IsWslInstalled())
|
||||
{
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.ErrorMsg,
|
||||
"WSL is not installed on this system. Please install WSL to use this protocol.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg,
|
||||
"Attempting to start WSL session.", true);
|
||||
|
||||
_consoleControl = new ConsoleControl.ConsoleControl
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
BackColor = ColorTranslator.FromHtml("#300A24"), // Ubuntu terminal color
|
||||
ForeColor = Color.White,
|
||||
IsInputEnabled = true,
|
||||
Padding = new Padding(0, 20, 0, 0)
|
||||
};
|
||||
|
||||
// Path to wsl.exe
|
||||
string wslExe = @"C:\Windows\System32\wsl.exe";
|
||||
|
||||
// Build arguments based on connection info
|
||||
string arguments = BuildWslArguments();
|
||||
|
||||
_consoleControl.StartProcess(wslExe, arguments);
|
||||
|
||||
while (!_consoleControl.IsHandleCreated) break;
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsWslInstalled()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if wsl.exe exists
|
||||
string wslPath = @"C:\Windows\System32\wsl.exe";
|
||||
if (!File.Exists(wslPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Additional check: Try to execute wsl.exe --status to verify it's properly installed
|
||||
// For now, just check if the file exists
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildWslArguments()
|
||||
{
|
||||
string arguments = "";
|
||||
|
||||
// If a hostname is specified, treat it as a distribution name
|
||||
if (!string.IsNullOrEmpty(_connectionInfo.Hostname))
|
||||
{
|
||||
string hostname = _connectionInfo.Hostname.Trim();
|
||||
// Check if it's not localhost (WSL doesn't use localhost as a distribution name)
|
||||
if (!hostname.Equals("localhost", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
arguments = $"-d {hostname}";
|
||||
}
|
||||
}
|
||||
|
||||
// If username is specified, we can try to use it
|
||||
if (!string.IsNullOrEmpty(_connectionInfo.Username))
|
||||
{
|
||||
arguments += $" -u {_connectionInfo.Username}";
|
||||
}
|
||||
|
||||
return arguments.Trim();
|
||||
}
|
||||
|
||||
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 = 0 // WSL doesn't use a traditional port
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
BIN
mRemoteNG/Icons/WSL.ico
Normal file
BIN
mRemoteNG/Icons/WSL.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -2190,4 +2190,7 @@ Le canal nightly inclut les versions alpha, beta et release candidates.</value>
|
||||
<data name="VaultOpenbaoSecretEngineLDAPStatic" type="System.Resources.ResXNullRef, System.Windows.Forms">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Wsl" xml:space="preserve">
|
||||
<value>WSL</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2396,4 +2396,7 @@ Kanał nocny obejmuje wersje alfa, beta i RC (gotowe do wydania).</value>
|
||||
<data name="VaultOpenbaoSecretEngineLDAPStatic" type="System.Resources.ResXNullRef, System.Windows.Forms">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Wsl" xml:space="preserve">
|
||||
<value>WSL</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2550,4 +2550,7 @@ Nightly Channel includes Alphas, Betas & Release Candidates.</value>
|
||||
<data name="FrameColorPurple" xml:space="preserve">
|
||||
<value>Purple (Custom)</value>
|
||||
</data>
|
||||
<data name="Wsl" xml:space="preserve">
|
||||
<value>WSL</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2453,4 +2453,7 @@
|
||||
<data name="VaultOpenbaoSecretEngineLDAPStatic" type="System.Resources.ResXNullRef, System.Windows.Forms">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Wsl" xml:space="preserve">
|
||||
<value>WSL</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2117,4 +2117,7 @@ mRemoteNG 将退出并安装更新。</value>
|
||||
<data name="VaultOpenbaoSecretEngineLDAPStatic" type="System.Resources.ResXNullRef, System.Windows.Forms">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Wsl" xml:space="preserve">
|
||||
<value>WSL</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -399,6 +399,9 @@
|
||||
<None Update="Icons\PowerShell.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Icons\WSL.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Icons\Production.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -332,6 +332,14 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||
nameof(ConnectionInfo.Port),
|
||||
});
|
||||
break;
|
||||
case ProtocolType.WSL:
|
||||
expectedProperties.AddRange(new[]
|
||||
{
|
||||
nameof(ConnectionInfo.Password),
|
||||
nameof(ConnectionInfo.Domain),
|
||||
nameof(ConnectionInfo.Port),
|
||||
});
|
||||
break;
|
||||
case ProtocolType.IntApp:
|
||||
expectedProperties.AddRange(new[]
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user