Merge pull request #1361 from mRemoteNG/feature/896_rdp_view_only

Implemented a view only mode for RDP
This commit is contained in:
David Sparer
2019-03-21 10:58:28 -05:00
committed by GitHub
10 changed files with 143 additions and 46 deletions

View File

@@ -1,4 +1,9 @@
using mRemoteNG.App;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using mRemoteNG.App;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.ICA;
@@ -10,11 +15,6 @@ using mRemoteNG.Connection.Protocol.Telnet;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Container;
using mRemoteNG.Tree;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace mRemoteNG.Connection
@@ -163,7 +163,8 @@ namespace mRemoteNG.Connection
DoNotJump = 4,
OverridePanel = 8,
DontUseConsoleSession = 16,
NoCredentials = 32
NoCredentials = 32,
ViewOnly = 64
}
#endregion

View File

@@ -0,0 +1,20 @@
namespace mRemoteNG.Connection.Protocol
{
/// <summary>
/// Signifies that a protocol supports View Only mode. When in View Only mode,
/// the control will not capture and send input events to the remote host.
/// </summary>
public interface ISupportsViewOnly
{
/// <summary>
/// Whether this control is in view only mode.
/// </summary>
bool ViewOnly { get; set; }
/// <summary>
/// Toggles whether the control will capture and send input events to the remote host.
/// The local host will continue to receive data from the remote host regardless of this setting.
/// </summary>
void ToggleViewOnly();
}
}

View File

@@ -1,3 +1,9 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using AxMSTSCLib;
using mRemoteNG.App;
using mRemoteNG.Messages;
@@ -6,16 +12,10 @@ using mRemoteNG.Tools;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using MSTSCLib;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace mRemoteNG.Connection.Protocol.RDP
{
public class RdpProtocol : ProtocolBase
public class RdpProtocol : ProtocolBase, ISupportsViewOnly
{
/* RDP v8 requires Windows 7 with:
* https://support.microsoft.com/en-us/kb/2592687
@@ -24,6 +24,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
*
* Windows 8+ support RDP v8 out of the box.
*/
private AxHost _axHost;
private MsRdpClient8NotSafeForScripting _rdpClient;
private Version _rdpVersion;
private ConnectionInfo _connectionInfo;
@@ -86,6 +87,12 @@ namespace mRemoteNG.Connection.Protocol.RDP
public bool LoadBalanceInfoUseUtf8 { get; set; }
public bool ViewOnly
{
get => !_axHost.Enabled;
set => _axHost.Enabled = !value;
}
#endregion
#region Constructors
@@ -116,7 +123,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
Application.DoEvents();
}
_rdpClient = (MsRdpClient8NotSafeForScripting)((AxMsRdpClient8NotSafeForScripting)Control).GetOcx();
_axHost = (AxMsRdpClient8NotSafeForScripting)Control;
_rdpClient = (MsRdpClient8NotSafeForScripting)_axHost.GetOcx();
}
catch (System.Runtime.InteropServices.COMException ex)
{
@@ -160,6 +168,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
SetAuthenticationLevel();
SetLoadBalanceInfo();
SetRdGateway();
ViewOnly = Force.HasFlag(ConnectionInfo.Force.ViewOnly);
_rdpClient.ColorDepth = (int)_connectionInfo.Colors;
@@ -187,6 +196,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
{
_rdpClient.Connect();
base.Connect();
return true;
}
catch (Exception ex)
@@ -234,6 +244,22 @@ namespace mRemoteNG.Connection.Protocol.RDP
}
}
/// <summary>
/// Toggles whether the RDP ActiveX control will capture and send input events to the remote host.
/// The local host will continue to receive data from the remote host regardless of this setting.
/// </summary>
public void ToggleViewOnly()
{
try
{
ViewOnly = !ViewOnly;
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, $"Could not toggle view only mode for host {_connectionInfo.Hostname}");
}
}
public override void Focus()
{
try

View File

@@ -1,15 +1,15 @@
using System;
using System.ComponentModel;
using mRemoteNG.App;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using System;
using System.ComponentModel;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.Connection.Protocol.VNC
{
public class ProtocolVNC : ProtocolBase
public class ProtocolVNC : ProtocolBase, ISupportsViewOnly
{
#region Properties

View File

@@ -105,6 +105,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Connect in View Only mode.
/// </summary>
internal static string ConnectInViewOnlyMode {
get {
return ResourceManager.GetString("ConnectInViewOnlyMode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The connection file could not be found..
/// </summary>
@@ -3984,7 +3993,7 @@ namespace mRemoteNG {
}
/// <summary>
/// Looks up a localized string similar to View Only (VNC).
/// Looks up a localized string similar to View Only.
/// </summary>
internal static string strMenuViewOnly {
get {

View File

@@ -1082,7 +1082,7 @@ Starte mit neuer Datei.</value>
<value>Text anzeigen</value>
</data>
<data name="strMenuSmartSize" xml:space="preserve">
<value>SmartSize (RDP/VNC)</value>
<value>Smart-Size-Modus (RDP/VNC)</value>
</data>
<data name="strMenuSSHFileTransfer" xml:space="preserve">
<value>SSH-Dateiübertragung</value>
@@ -1103,7 +1103,7 @@ Starte mit neuer Datei.</value>
<value>&amp;Ansicht</value>
</data>
<data name="strMenuViewOnly" xml:space="preserve">
<value>Nur Ansicht (VNC)</value>
<value>View-Only-Modus</value>
</data>
<data name="strMenuWebsite" xml:space="preserve">
<value>Webseite</value>
@@ -1157,7 +1157,7 @@ Starte mit neuer Datei.</value>
<value>Normal</value>
</data>
<data name="strNoSmartSize" xml:space="preserve">
<value>Keine automatische Größenanpassung (SmartSize)</value>
<value>Keine automatische Größenanpassung (Smart-Size)</value>
</data>
<data name="strNoUpdateAvailable" xml:space="preserve">
<value>Keine Updates verfügbar</value>
@@ -1467,7 +1467,7 @@ Wenn Sie Fehler feststellen, dann sollten Sie eine neue Verbindungsdatei erstell
<value>Auflösung</value>
</data>
<data name="strPropertyNameSmartSizeMode" xml:space="preserve">
<value>SmartSize-Modus</value>
<value>Smart-Size-Modus</value>
</data>
<data name="strPropertyNameUseConsoleSession" xml:space="preserve">
<value>Verwende Konsole</value>
@@ -2660,4 +2660,7 @@ Development umfasst Alphas, Betas und Release Candidates.</value>
<data name="Favorites" xml:space="preserve">
<value>Favoriten</value>
</data>
<data name="ConnectInViewOnlyMode" xml:space="preserve">
<value>Im View-Only-Modus verbinden</value>
</data>
</root>

View File

@@ -1220,7 +1220,7 @@ See the Microsoft Support article at http://support.microsoft.com/kb/811833 for
<value>&amp;View</value>
</data>
<data name="strMenuViewOnly" xml:space="preserve">
<value>View Only (VNC)</value>
<value>View Only</value>
</data>
<data name="strMenuWebsite" xml:space="preserve">
<value>Website</value>
@@ -2761,11 +2761,11 @@ Development Channel includes Alphas, Betas &amp; Release Candidates.</value>
<value>Proxy</value>
</data>
<data name="strMultiSSH" xml:space="preserve">
<value>Multi SSH:</value>
</data>
<value>Multi SSH:</value>
</data>
<data name="strMultiSSHToolTip" xml:space="preserve">
<value>Press ENTER to send. Ctrl+C is sent immediately.</value>
</data>
<value>Press ENTER to send. Ctrl+C is sent immediately.</value>
</data>
<data name="strPropertyDescriptionFavorite" xml:space="preserve">
<value>Show this connection in the favorites menu.</value>
</data>
@@ -2775,4 +2775,7 @@ Development Channel includes Alphas, Betas &amp; Release Candidates.</value>
<data name="Favorites" xml:space="preserve">
<value>Favorites</value>
</data>
<data name="ConnectInViewOnlyMode" xml:space="preserve">
<value>Connect in View Only mode</value>
</data>
</root>

View File

@@ -26,6 +26,7 @@ namespace mRemoteNG.UI.Controls
private ToolStripMenuItem _cMenTreeConnectWithOptionsConnectToConsoleSession;
private ToolStripMenuItem _cMenTreeConnectWithOptionsNoCredentials;
private ToolStripMenuItem _cMenTreeConnectWithOptionsConnectInFullscreen;
private ToolStripMenuItem _cMenTreeConnectWithOptionsViewOnly;
private ToolStripMenuItem _cMenTreeDisconnect;
private ToolStripSeparator _cMenTreeSep2;
private ToolStripMenuItem _cMenTreeToolsTransferFile;
@@ -82,6 +83,7 @@ namespace mRemoteNG.UI.Controls
_cMenTreeConnectWithOptionsConnectInFullscreen = new ToolStripMenuItem();
_cMenTreeConnectWithOptionsNoCredentials = new ToolStripMenuItem();
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting = new ToolStripMenuItem();
_cMenTreeConnectWithOptionsViewOnly = new ToolStripMenuItem();
_cMenTreeDisconnect = new ToolStripMenuItem();
_cMenTreeSep1 = new ToolStripSeparator();
_cMenTreeToolsExternalApps = new ToolStripMenuItem();
@@ -157,7 +159,8 @@ namespace mRemoteNG.UI.Controls
_cMenTreeConnectWithOptionsDontConnectToConsoleSession,
_cMenTreeConnectWithOptionsConnectInFullscreen,
_cMenTreeConnectWithOptionsNoCredentials,
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting,
_cMenTreeConnectWithOptionsViewOnly
});
_cMenTreeConnectWithOptions.Name = "_cMenTreeConnectWithOptions";
_cMenTreeConnectWithOptions.Size = new System.Drawing.Size(199, 22);
@@ -207,6 +210,15 @@ namespace mRemoteNG.UI.Controls
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting.Text = "Choose panel before connecting";
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting.Click += OnChoosePanelBeforeConnectingClicked;
//
// cMenTreeConnectWithOptionsViewOnly
//
_cMenTreeConnectWithOptionsViewOnly.Image = Resources.View;
_cMenTreeConnectWithOptionsViewOnly.Name =
"_cMenTreeConnectWithOptionsViewOnly";
_cMenTreeConnectWithOptionsViewOnly.Size = new System.Drawing.Size(245, 22);
_cMenTreeConnectWithOptionsViewOnly.Text = Language.ConnectInViewOnlyMode;
_cMenTreeConnectWithOptionsViewOnly.Click += ConnectWithOptionsViewOnlyOnClick;
//
// cMenTreeDisconnect
//
_cMenTreeDisconnect.Image = Resources.Pause;
@@ -396,6 +408,7 @@ namespace mRemoteNG.UI.Controls
_cMenTreeConnectWithOptionsConnectInFullscreen.Text = Language.strConnectInFullscreen;
_cMenTreeConnectWithOptionsNoCredentials.Text = Language.strConnectNoCredentials;
_cMenTreeConnectWithOptionsChoosePanelBeforeConnecting.Text = Language.strChoosePanelBeforeConnecting;
_cMenTreeConnectWithOptionsViewOnly.Text = Language.ConnectInViewOnlyMode;
_cMenTreeDisconnect.Text = Language.strMenuDisconnect;
_cMenTreeToolsExternalApps.Text = Language.strMenuExternalTools;
@@ -436,13 +449,13 @@ namespace mRemoteNG.UI.Controls
{
ShowHideMenuItemsForRootConnectionNode();
}
else if (_connectionTree.SelectedNode is ContainerInfo)
else if (_connectionTree.SelectedNode is ContainerInfo containerInfo)
{
ShowHideMenuItemsForContainer(_connectionTree.SelectedNode);
ShowHideMenuItemsForContainer(containerInfo);
}
else if (_connectionTree.SelectedNode is PuttySessionInfo)
else if (_connectionTree.SelectedNode is PuttySessionInfo puttyNode)
{
ShowHideMenuItemsForPuttyNode(_connectionTree.SelectedNode);
ShowHideMenuItemsForPuttyNode(puttyNode);
}
else
{
@@ -475,6 +488,7 @@ namespace mRemoteNG.UI.Controls
_cMenTreeDelete.Enabled = false;
_cMenTreeMoveUp.Enabled = false;
_cMenTreeMoveDown.Enabled = false;
_cMenTreeConnectWithOptionsViewOnly.Enabled = false;
}
internal void ShowHideMenuItemsForRootConnectionNode()
@@ -491,22 +505,22 @@ namespace mRemoteNG.UI.Controls
_cMenTreeDelete.Enabled = false;
_cMenTreeMoveUp.Enabled = false;
_cMenTreeMoveDown.Enabled = false;
_cMenTreeConnectWithOptionsViewOnly.Enabled = false;
}
internal void ShowHideMenuItemsForContainer(ConnectionInfo connectionInfo)
internal void ShowHideMenuItemsForContainer(ContainerInfo containerInfo)
{
_cMenTreeConnectWithOptionsConnectInFullscreen.Enabled = false;
_cMenTreeConnectWithOptionsConnectToConsoleSession.Enabled = false;
_cMenTreeDisconnect.Enabled = false;
var openConnections = ((ContainerInfo)connectionInfo).Children.Sum(child => child.OpenConnections.Count);
if (openConnections > 0)
_cMenTreeDisconnect.Enabled = true;
var hasOpenConnections = containerInfo.Children.Any(child => child.OpenConnections.Count > 0);
_cMenTreeDisconnect.Enabled = hasOpenConnections;
_cMenTreeToolsTransferFile.Enabled = false;
_cMenTreeConnectWithOptionsViewOnly.Enabled = false;
}
internal void ShowHideMenuItemsForPuttyNode(ConnectionInfo connectionInfo)
internal void ShowHideMenuItemsForPuttyNode(PuttySessionInfo connectionInfo)
{
_cMenTreeAddConnection.Enabled = false;
_cMenTreeAddFolder.Enabled = false;
@@ -527,6 +541,7 @@ namespace mRemoteNG.UI.Controls
_cMenTreeMoveDown.Enabled = false;
_cMenTreeImport.Enabled = false;
_cMenTreeExportFile.Enabled = false;
_cMenTreeConnectWithOptionsViewOnly.Enabled = false;
}
internal void ShowHideMenuItemsForConnectionNode(ConnectionInfo connectionInfo)
@@ -545,6 +560,9 @@ namespace mRemoteNG.UI.Controls
if (connectionInfo.Protocol == ProtocolType.IntApp)
_cMenTreeConnectWithOptionsNoCredentials.Enabled = false;
if (connectionInfo.Protocol != ProtocolType.RDP && connectionInfo.Protocol != ProtocolType.VNC)
_cMenTreeConnectWithOptionsViewOnly.Enabled = false;
}
internal void DisableShortcutKeys()
@@ -691,6 +709,13 @@ namespace mRemoteNG.UI.Controls
ConnectionInfo.Force.DoNotJump);
}
private void ConnectWithOptionsViewOnlyOnClick(object sender, EventArgs e)
{
var connectionTarget = _connectionTree.SelectedNode as ContainerInfo
?? _connectionTree.SelectedNode;
_connectionInitiator.OpenConnection(connectionTarget, ConnectionInfo.Force.ViewOnly);
}
private void OnDisconnectClicked(object sender, EventArgs e)
{
DisconnectConnection(_connectionTree.SelectedNode);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
@@ -15,9 +15,9 @@ using mRemoteNG.Themes;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Forms.Input;
using mRemoteNG.UI.Tabs;
using mRemoteNG.UI.TaskDialog;
using WeifenLuo.WinFormsUI.Docking;
using mRemoteNG.UI.Tabs;
namespace mRemoteNG.UI.Window
{
@@ -363,6 +363,16 @@ namespace mRemoteNG.UI.Window
var interfaceControl = GetInterfaceControl();
if (interfaceControl == null) return;
if (interfaceControl.Protocol is ISupportsViewOnly viewOnly)
{
cmenTabViewOnly.Visible = true;
cmenTabViewOnly.Checked = viewOnly.ViewOnly;
}
else
{
cmenTabViewOnly.Visible = false;
}
if (interfaceControl.Info.Protocol == ProtocolType.RDP)
{
var rdp = (RdpProtocol)interfaceControl.Protocol;
@@ -381,18 +391,15 @@ namespace mRemoteNG.UI.Window
{
var vnc = (ProtocolVNC)interfaceControl.Protocol;
cmenTabSendSpecialKeys.Visible = true;
cmenTabViewOnly.Visible = true;
cmenTabSmartSize.Visible = true;
cmenTabStartChat.Visible = true;
cmenTabRefreshScreen.Visible = true;
cmenTabTransferFile.Visible = false;
cmenTabSmartSize.Checked = vnc.SmartSize;
cmenTabViewOnly.Checked = vnc.ViewOnly;
}
else
{
cmenTabSendSpecialKeys.Visible = false;
cmenTabViewOnly.Visible = false;
cmenTabStartChat.Visible = false;
cmenTabRefreshScreen.Visible = false;
cmenTabTransferFile.Visible = false;
@@ -500,9 +507,11 @@ namespace mRemoteNG.UI.Window
try
{
var interfaceControl = GetInterfaceControl();
if (!(interfaceControl?.Protocol is ProtocolVNC vnc)) return;
if (!(interfaceControl?.Protocol is ISupportsViewOnly viewOnly))
return;
cmenTabViewOnly.Checked = !cmenTabViewOnly.Checked;
vnc.ToggleViewOnly();
viewOnly.ToggleViewOnly();
}
catch (Exception ex)
{

View File

@@ -249,6 +249,7 @@
<Compile Include="Connection\Protocol\Http\Connection.Protocol.HTTPS.CertEvent.cs" />
<Compile Include="Connection\Protocol\ProtocolFactory.cs" />
<Compile Include="Connection\Protocol\RDP\AzureLoadBalanceInfoEncoder.cs" />
<Compile Include="Connection\Protocol\ISupportsViewOnly.cs" />
<Compile Include="Connection\Protocol\RDP\RdpClientWrap.cs">
<SubType>Component</SubType>
</Compile>