mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Added PowerShell Protocol for remote PS-Sessions
This commit is contained in:
@@ -342,6 +342,15 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||
nameof(ConnectionInfo.CacheBitmaps),
|
||||
});
|
||||
break;
|
||||
case ProtocolType.PowerShell:
|
||||
expectedProperties.AddRange(new[]
|
||||
{
|
||||
nameof(ConnectionInfo.Username),
|
||||
nameof(ConnectionInfo.Password),
|
||||
nameof(ConnectionInfo.Domain),
|
||||
nameof(ConnectionInfo.Port),
|
||||
});
|
||||
break;
|
||||
case ProtocolType.IntApp:
|
||||
expectedProperties.AddRange(new[]
|
||||
{
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
|
||||
LocalizedAttributes.LocalizedDisplayName("strPropertyNameDomain"),
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDomain"),
|
||||
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA, ProtocolType.IntApp)]
|
||||
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA, ProtocolType.IntApp, ProtocolType.PowerShell)]
|
||||
public string Domain
|
||||
{
|
||||
get => GetPropertyValue("Domain", _domain).Trim();
|
||||
|
||||
@@ -7,6 +7,7 @@ using mRemoteNG.App;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Connection.Protocol.Http;
|
||||
using mRemoteNG.Connection.Protocol.ICA;
|
||||
using mRemoteNG.Connection.Protocol.PowerShell;
|
||||
using mRemoteNG.Connection.Protocol.RAW;
|
||||
using mRemoteNG.Connection.Protocol.RDP;
|
||||
using mRemoteNG.Connection.Protocol.Rlogin;
|
||||
@@ -265,6 +266,8 @@ namespace mRemoteNG.Connection
|
||||
return (int)ProtocolHTTPS.Defaults.Port;
|
||||
case ProtocolType.ICA:
|
||||
return (int)IcaProtocol.Defaults.Port;
|
||||
case ProtocolType.PowerShell:
|
||||
return (int)ProtocolPowerShell.Defaults.Port;
|
||||
case ProtocolType.IntApp:
|
||||
return (int)IntegratedProgram.Defaults.Port;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol.PowerShell
|
||||
{
|
||||
public class ProtocolPowerShell : ProtocolBase
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private IntPtr _handle;
|
||||
private Process _process;
|
||||
private readonly ConnectionInfo _connectionInfo;
|
||||
|
||||
public ProtocolPowerShell(ConnectionInfo connectionInfo)
|
||||
{
|
||||
_connectionInfo = connectionInfo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg,
|
||||
$"Attempting to start remote PowerShell session.", true);
|
||||
|
||||
_process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = @"C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe",
|
||||
Arguments = $@"-NoExit -Command ""$password = ConvertTo-SecureString '{_connectionInfo.Password}' -AsPlainText -Force; $cred = New-Object System.Management.Automation.PSCredential -ArgumentList @('{_connectionInfo.Domain}\{_connectionInfo.Username}', $password); Enter-PSSession -ComputerName {_connectionInfo.Hostname} -Credential $cred"""
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
_process.Exited += ProcessExited;
|
||||
|
||||
_process.Start();
|
||||
Thread.Sleep(500);
|
||||
//_process.WaitForInputIdle();
|
||||
NativeMethods.SetParent(_process.MainWindowHandle, InterfaceControl.Handle);
|
||||
|
||||
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg, Language.strIntAppStuff, true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg,
|
||||
string.Format(Language.strIntAppHandle, _handle), true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg,
|
||||
string.Format(Language.strIntAppTitle, _process.MainWindowTitle),
|
||||
true);
|
||||
Runtime.MessageCollector?.AddMessage(MessageClass.InformationMsg,
|
||||
string.Format(Language.strIntAppParentHandle,
|
||||
InterfaceControl.Parent.Handle), true);
|
||||
|
||||
Resize(this, new EventArgs());
|
||||
base.Connect();
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector?.AddExceptionMessage(Language.strIntAppConnectionFailed, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
|
||||
|
||||
public override void Focus()
|
||||
{
|
||||
try
|
||||
{
|
||||
NativeMethods.SetForegroundWindow(_handle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppFocusFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resize(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InterfaceControl.Size == Size.Empty) return;
|
||||
NativeMethods.MoveWindow(_handle, -SystemInformation.FrameBorderSize.Width,
|
||||
-(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height),
|
||||
InterfaceControl.Width + SystemInformation.FrameBorderSize.Width * 2,
|
||||
InterfaceControl.Height + SystemInformation.CaptionHeight +
|
||||
SystemInformation.FrameBorderSize.Height * 2, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppResizeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
/* only attempt this if we have a valid process object
|
||||
* Non-integrated tools will still call base.Close() and don't have a valid process object.
|
||||
* See Connect() above... This just muddies up the log.
|
||||
*/
|
||||
if (_process != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppKillFailed, ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(Language.strIntAppDisposeFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
base.Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void ProcessExited(object sender, EventArgs e)
|
||||
{
|
||||
Event_Closed(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enumerations
|
||||
|
||||
public enum Defaults
|
||||
{
|
||||
Port = 5985
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using mRemoteNG.Connection.Protocol.SSH;
|
||||
using mRemoteNG.Connection.Protocol.Telnet;
|
||||
using mRemoteNG.Connection.Protocol.VNC;
|
||||
using System;
|
||||
using mRemoteNG.Connection.Protocol.PowerShell;
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
@@ -43,6 +44,8 @@ namespace mRemoteNG.Connection.Protocol
|
||||
var icaProtocol = new IcaProtocol();
|
||||
icaProtocol.tmrReconnect.Elapsed += icaProtocol.tmrReconnect_Elapsed;
|
||||
return icaProtocol;
|
||||
case ProtocolType.PowerShell:
|
||||
return new ProtocolPowerShell(connectionInfo);
|
||||
case ProtocolType.IntApp:
|
||||
if (connectionInfo.ExtApp == "")
|
||||
{
|
||||
@@ -51,7 +54,7 @@ namespace mRemoteNG.Connection.Protocol
|
||||
return new IntegratedProgram();
|
||||
}
|
||||
|
||||
return default(ProtocolBase);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.Connection.Protocol
|
||||
{
|
||||
@@ -34,6 +34,9 @@ namespace mRemoteNG.Connection.Protocol
|
||||
[LocalizedAttributes.LocalizedDescription("strICA")]
|
||||
ICA = 9,
|
||||
|
||||
[LocalizedAttributes.LocalizedDescription("strPowerShell")]
|
||||
PowerShell = 10,
|
||||
|
||||
[LocalizedAttributes.LocalizedDescription("strExtApp")]
|
||||
IntApp = 20
|
||||
}
|
||||
|
||||
11
mRemoteV1/Resources/Language/Language.Designer.cs
generated
11
mRemoteV1/Resources/Language/Language.Designer.cs
generated
@@ -5694,6 +5694,17 @@ namespace mRemoteNG
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PowerShell.
|
||||
/// </summary>
|
||||
internal static string strPowerShell
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("strPowerShell", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to (These properties will only be saved if you select mRemote/mRemoteNG XML as output file format!).
|
||||
/// </summary>
|
||||
|
||||
@@ -2825,4 +2825,7 @@ Development Channel includes Alphas, Betas & Release Candidates.</value>
|
||||
<data name="strPropertyDescriptionPasswordProtect" xml:space="preserve">
|
||||
<value>Set a password needed to encrypt the connection file with. You will be prompted to enter your passcode before starting mRemoteNG.</value>
|
||||
</data>
|
||||
<data name="strPowerShell" xml:space="preserve">
|
||||
<value>PowerShell</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -285,6 +285,7 @@
|
||||
<Compile Include="Credential\Repositories\CredentialRepoUnlockerBuilder.cs" />
|
||||
<Compile Include="Credential\CredentialServiceFactory.cs" />
|
||||
<Compile Include="Credential\CredentialServiceFacade.cs" />
|
||||
<Compile Include="Connection\Protocol\PowerShell\Connection.Protocol.PowerShell.cs" />
|
||||
<None Include="Documentation\faq.rst" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
|
||||
Reference in New Issue
Block a user